Files
notesnook/apps/mobile/src/components/RecoveryKeyDialog/index.js

264 lines
6.9 KiB
JavaScript
Raw Normal View History

2021-02-10 13:02:57 +05:00
import React, {createRef} from 'react';
import {Clipboard, View} from 'react-native';
2020-09-24 17:39:53 +05:00
import QRCode from 'react-native-qrcode-svg';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
2021-02-10 21:57:08 +05:00
2021-02-10 13:02:57 +05:00
import {LOGO_BASE64} from '../../assets/images/assets';
2020-10-28 11:26:58 +05:00
import {
2020-10-28 15:15:35 +05:00
eSendEvent,
2020-10-28 11:26:58 +05:00
eSubscribeEvent,
eUnSubscribeEvent,
2021-02-10 13:02:57 +05:00
ToastEvent,
2020-10-28 11:26:58 +05:00
} from '../../services/EventManager';
2021-02-10 13:02:57 +05:00
import {dWidth} from '../../utils';
import {db} from '../../utils/DB';
import {eOpenRecoveryKeyDialog, eOpenResultDialog} from '../../utils/Events';
import {SIZE} from '../../utils/SizeUtils';
2020-11-23 12:32:33 +05:00
import Storage from '../../utils/storage';
2021-02-10 13:02:57 +05:00
import {sleep} from '../../utils/TimeUtils';
2020-12-28 12:50:02 +05:00
import ActionSheetWrapper from '../ActionSheetComponent/ActionSheetWrapper';
2021-02-10 13:02:57 +05:00
import {Button} from '../Button';
import DialogHeader from '../Dialog/dialog-header';
2020-09-24 17:39:53 +05:00
import Seperator from '../Seperator';
2021-02-10 13:02:57 +05:00
import {Toast} from '../Toast';
2020-11-20 01:23:05 +05:00
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
2021-02-10 21:57:08 +05:00
let RNFetchBlob;
2020-09-24 17:39:53 +05:00
class RecoveryKeyDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
key: null,
2020-11-23 12:32:33 +05:00
visible: false,
2020-09-24 17:39:53 +05:00
};
this.actionSheetRef = createRef();
this.svg = createRef();
2020-10-28 11:26:58 +05:00
this.user;
2020-10-28 15:15:35 +05:00
this.signup = false;
2021-02-10 13:02:57 +05:00
this.tapCount = 0;
2020-09-24 17:39:53 +05:00
}
2020-10-28 15:15:35 +05:00
open = (signup) => {
if (signup) {
this.signup = true;
}
2020-11-23 12:32:33 +05:00
this.setState(
{
visible: true,
},
() => {
2020-12-29 11:25:12 +05:00
this.actionSheetRef.current?.setModalVisible(true);
2020-11-23 12:32:33 +05:00
},
);
2020-09-24 17:39:53 +05:00
};
close = () => {
2021-02-10 13:02:57 +05:00
if (this.tapCount === 0) {
ToastEvent.show('Tap one more time to confirm.', 'error', 'local');
this.tapCount++;
return;
}
this.tapCount = 0;
2020-12-29 11:25:12 +05:00
this.actionSheetRef.current?.setModalVisible(false);
2020-11-23 12:32:33 +05:00
sleep(200).then(() => {
this.setState({
visible: false,
});
});
2020-10-28 15:52:15 +05:00
if (this.signup) {
2020-10-28 15:15:35 +05:00
setTimeout(() => {
eSendEvent(eOpenResultDialog, {
title: 'Welcome!',
2020-12-28 12:50:02 +05:00
paragraph: 'Please verify your email to activate syncing.',
icon: 'check',
2020-10-28 15:15:35 +05:00
button: 'Thank You!',
});
}, 500);
}
2020-09-24 17:39:53 +05:00
};
async componentDidMount() {
eSubscribeEvent(eOpenRecoveryKeyDialog, this.open);
}
async componentWillUnmount() {
eUnSubscribeEvent(eOpenRecoveryKeyDialog, this.open);
}
2020-10-28 11:26:58 +05:00
saveQRCODE = async () => {
2021-02-10 21:57:08 +05:00
2020-10-28 11:26:58 +05:00
if ((await Storage.requestPermission()) === false) {
ToastEvent.show('Storage access not granted!', 'error', 'local');
return;
}
2020-09-24 17:39:53 +05:00
2020-10-28 11:26:58 +05:00
this.svg.current?.toDataURL(async (data) => {
let path = await Storage.checkAndCreateDir('/');
2021-02-10 21:57:08 +05:00
RNFetchBlob = require("rn-fetch-blob");
2020-12-16 12:52:00 +05:00
let fileName = 'nn_' + this.user.email + '_recovery_key_qrcode.png';
2020-10-28 11:26:58 +05:00
RNFetchBlob.fs.writeFile(path + fileName, data, 'base64').then((res) => {
RNFetchBlob.fs
.scanFile([
{
path: path + fileName,
mime: 'image/png',
},
])
.then((r) => {
ToastEvent.show(
'Recovery key saved to Gallery as ' + path + fileName,
'success',
'local',
);
});
});
2020-09-24 17:39:53 +05:00
});
};
2020-10-28 11:26:58 +05:00
saveToTextFile = async () => {
2021-02-10 21:57:08 +05:00
2020-10-28 11:26:58 +05:00
if ((await Storage.requestPermission()) === false) {
ToastEvent.show('Storage access not granted!', 'error', 'local');
return;
}
let path = await Storage.checkAndCreateDir('/');
2020-12-16 12:52:00 +05:00
let fileName = 'nn_' + this.user.email + '_recovery_key.txt';
2021-02-10 21:57:08 +05:00
RNFetchBlob = require("rn-fetch-blob");
2020-10-28 11:26:58 +05:00
RNFetchBlob.fs
.writeFile(path + fileName, this.state.key, 'utf8')
.then((r) => {
ToastEvent.show(
'Recovery key saved as ' + path + fileName,
'success',
'local',
);
})
.catch((e) => {});
};
onOpen = async () => {
2020-12-20 12:48:08 +05:00
let k = await db.user.getEncryptionKey();
2020-12-16 14:57:58 +05:00
this.user = await db.user.getUser();
2020-11-20 02:43:07 +05:00
2020-10-28 11:26:58 +05:00
if (k) {
this.setState({
key: k.key,
});
}
};
2020-09-24 17:39:53 +05:00
render() {
const {colors} = this.props;
2020-11-23 12:32:33 +05:00
if (!this.state.visible) return null;
2020-09-24 17:39:53 +05:00
return (
2020-12-28 12:50:02 +05:00
<ActionSheetWrapper
2020-10-28 15:15:35 +05:00
closeOnTouchBackdrop={false}
2020-12-28 12:50:02 +05:00
gestureEnabled={false}
2020-10-28 11:26:58 +05:00
onOpen={this.onOpen}
2020-12-28 12:50:02 +05:00
fwdRef={this.actionSheetRef}>
2020-09-24 17:39:53 +05:00
<View
style={{
2021-02-10 13:02:57 +05:00
width: '100%',
2020-09-24 17:39:53 +05:00
backgroundColor: colors.bg,
justifyContent: 'space-between',
paddingHorizontal: 12,
borderRadius: 10,
paddingTop: 10,
}}>
2021-02-10 13:02:57 +05:00
<DialogHeader
title="Your Data Recovery Key"
paragraph="If you forget your password, you can recover your
data and reset your password using your data recovery key."
/>
2020-09-24 23:01:35 +05:00
2020-09-24 17:39:53 +05:00
<View
style={{
2020-09-24 23:01:35 +05:00
backgroundColor: colors.nav,
2020-09-24 17:39:53 +05:00
borderRadius: 5,
2020-09-24 23:01:35 +05:00
padding: 10,
marginTop: 10,
2020-09-24 17:39:53 +05:00
}}>
2020-11-20 01:23:05 +05:00
<Paragraph
color={colors.icon}
size={SIZE.md}
2020-09-24 17:39:53 +05:00
numberOfLines={2}
style={{
width: '100%',
maxWidth: '100%',
paddingRight: 10,
}}>
{this.state.key}
2020-11-20 01:23:05 +05:00
</Paragraph>
2021-02-10 13:02:57 +05:00
<Button
onPress={() => {
Clipboard.setString(this.state.key);
ToastEvent.show('Copied!', 'success', 'local');
}}
icon="content-copy"
title="Copy to Clipboard"
width="100%"
type="gray"
fontSize={SIZE.md}
height={50}
/>
2020-09-24 23:01:35 +05:00
</View>
<Seperator />
<View
style={{
alignSelf: 'center',
marginBottom: 15,
flexDirection: 'row',
width: '100%',
2021-02-10 13:02:57 +05:00
justifyContent: 'center',
position: 'absolute',
opacity: 0,
2020-09-24 23:01:35 +05:00
}}>
{this.state.key ? (
<QRCode
getRef={this.svg}
2021-02-10 13:02:57 +05:00
size={500}
value={this.state.key}
logo={{uri: LOGO_BASE64}}
logoBorderRadius={10}
/>
) : null}
2020-09-24 17:39:53 +05:00
</View>
2021-02-10 13:02:57 +05:00
<Button
title="Save QR-Code to Gallery"
onPress={this.saveQRCODE}
width="100%"
type="accent"
fontSize={SIZE.md}
height={50}
/>
2020-09-24 17:39:53 +05:00
<Seperator />
2021-02-10 13:02:57 +05:00
<Button
onPress={this.saveToTextFile}
title="Save to Text File"
width="100%"
type="accent"
fontSize={SIZE.md}
height={50}
/>
2020-10-28 15:15:35 +05:00
<Seperator />
<Button
2021-02-10 13:02:57 +05:00
title="I Have Saved the Key."
2020-10-28 15:15:35 +05:00
width="100%"
height={50}
2021-02-10 13:02:57 +05:00
type="error"
fontSize={SIZE.md}
2020-10-28 15:15:35 +05:00
onPress={this.close}
/>
2020-09-24 17:39:53 +05:00
<Toast context="local" />
</View>
2020-12-28 12:50:02 +05:00
</ActionSheetWrapper>
2020-09-24 17:39:53 +05:00
);
}
}
export default RecoveryKeyDialog;