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

286 lines
7.7 KiB
JavaScript
Raw Normal View History

2020-11-23 12:32:33 +05:00
import React, { createRef } from 'react';
2020-12-07 11:16:41 +05:00
import { Clipboard, Platform, 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';
import RNFetchBlob from 'rn-fetch-blob';
2020-11-23 12:32:33 +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,
2020-11-23 12:32:33 +05:00
ToastEvent
2020-10-28 11:26:58 +05:00
} from '../../services/EventManager';
2020-11-23 12:32:33 +05:00
import { dWidth } from '../../utils';
2020-12-07 11:16:41 +05:00
import { hexToRGBA } from '../../utils/ColorUtils';
2020-11-23 12:32:33 +05:00
import { db } from '../../utils/DB';
import { eOpenRecoveryKeyDialog, eOpenResultDialog } from '../../utils/Events';
import { SIZE } from '../../utils/SizeUtils';
import Storage from '../../utils/storage';
import { sleep } from '../../utils/TimeUtils';
2020-09-24 17:39:53 +05:00
import ActionSheet from '../ActionSheet';
2020-11-23 12:32:33 +05:00
import { Button } from '../Button';
2020-09-24 17:39:53 +05:00
import Seperator from '../Seperator';
2020-11-23 12:32:33 +05:00
import { Toast } from '../Toast';
2020-11-20 01:23:05 +05:00
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
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;
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,
},
() => {
this.actionSheetRef.current?._setModalVisible(true);
},
);
2020-09-24 17:39:53 +05:00
};
close = () => {
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!',
paragraph: 'Your 14 day trial for Notesnook Pro is activated',
icon: 'checkbox-marked-circle',
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 () => {
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('/');
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 () => {
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';
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 (
<ActionSheet
containerStyle={{
backgroundColor: colors.bg,
width: '100%',
alignSelf: 'center',
borderRadius: 10,
}}
2020-12-07 11:16:41 +05:00
indicatorColor={
Platform.ios
? hexToRGBA(colors.accent + '19')
: hexToRGBA(colors.shade)
}
2020-12-09 22:16:44 +05:00
extraScroll={20}
2020-10-28 15:15:35 +05:00
closeOnTouchBackdrop={false}
2020-10-28 11:26:58 +05:00
onOpen={this.onOpen}
2020-09-24 17:39:53 +05:00
ref={this.actionSheetRef}
initialOffsetFromBottom={1}>
<View
style={{
2020-10-13 17:02:14 +05:00
width: dWidth,
2020-09-24 17:39:53 +05:00
backgroundColor: colors.bg,
justifyContent: 'space-between',
paddingHorizontal: 12,
borderRadius: 10,
paddingTop: 10,
}}>
2020-11-20 01:23:05 +05:00
<Heading
2020-09-24 23:01:35 +05:00
numberOfLines={2}
style={{
width: '85%',
maxWidth: '85%',
paddingRight: 10,
marginTop: 10,
}}>
2020-11-20 01:23:05 +05:00
Recovery Key
</Heading>
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>
2020-09-24 23:01:35 +05:00
</View>
<Seperator />
<View
style={{
alignSelf: 'center',
marginBottom: 15,
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
}}>
{this.state.key ? (
<QRCode
getRef={this.svg}
2020-10-13 17:02:14 +05:00
size={dWidth / 2.2}
value={this.state.key}
logo={{uri: LOGO_BASE64}}
logoBorderRadius={10}
/>
) : null}
2020-09-24 23:01:35 +05:00
2020-09-24 17:39:53 +05:00
<Seperator />
<View
style={{
2020-09-24 23:01:35 +05:00
alignItems: 'center',
2020-10-13 17:02:14 +05:00
width: dWidth / 2.2,
2020-09-24 23:01:35 +05:00
justifyContent: 'center',
2020-09-24 17:39:53 +05:00
}}>
2020-09-24 23:01:35 +05:00
<Button
title="Save to Gallery"
onPress={this.saveQRCODE}
width="100%"
height={40}
/>
<Seperator />
2020-09-24 17:39:53 +05:00
<Button
2020-10-28 11:26:58 +05:00
onPress={this.saveToTextFile}
2020-09-24 23:01:35 +05:00
title="Save as Text File"
width="100%"
height={40}
2020-09-24 17:39:53 +05:00
/>
2020-09-24 23:01:35 +05:00
<Seperator />
2020-09-24 17:39:53 +05:00
<Button
onPress={() => {
Clipboard.setString(this.state.key);
2020-10-28 11:26:58 +05:00
ToastEvent.show('Copied!', 'success', 'local');
2020-09-24 17:39:53 +05:00
}}
2020-09-24 23:01:35 +05:00
title="Copy Key"
width="100%"
height={40}
2020-09-24 17:39:53 +05:00
/>
</View>
</View>
<Seperator />
<View
style={{
flexDirection: 'row',
padding: 10,
borderRadius: 10,
}}>
<Icon color={colors.errorText} size={SIZE.lg} name="alert-circle" />
2020-11-20 01:23:05 +05:00
<Paragraph
color={colors.errorText}
2020-09-24 17:39:53 +05:00
style={{
marginLeft: 10,
width: '90%',
}}>
We request you to save your recovery key and keep it in multiple
places. If you forget your password, you can only recover your
data or reset your password using this recovery key.
2020-11-20 01:23:05 +05:00
</Paragraph>
2020-09-24 17:39:53 +05:00
</View>
2020-10-28 15:15:35 +05:00
<Seperator />
<Button
title="I have saved the key."
width="100%"
height={50}
2020-11-14 11:38:31 +05:00
type="accent"
2020-10-28 15:15:35 +05:00
onPress={this.close}
/>
2020-09-24 17:39:53 +05:00
<Toast context="local" />
</View>
</ActionSheet>
);
}
}
export default RecoveryKeyDialog;