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

482 lines
13 KiB
JavaScript
Raw Normal View History

2020-03-03 15:37:48 +05:00
import React, {Component, createRef} from 'react';
2020-03-10 23:19:16 +05:00
import {View, Text, TouchableOpacity, Modal, ToastAndroid} from 'react-native';
2019-12-14 19:26:44 +05:00
import {SIZE, ph, pv, opacity, WEIGHT} from '../../common/common';
2020-02-11 20:33:36 +05:00
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
2020-01-17 21:05:38 +05:00
import {TextInput} from 'react-native-gesture-handler';
2020-03-14 13:54:16 +05:00
import {getElevation, ToastEvent, db, DDS} from '../../utils/utils';
2020-03-02 13:52:09 +05:00
import Share from 'react-native-share';
2020-03-10 23:19:16 +05:00
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent,
} from '../../services/eventManager';
import {
eOnLoadNote,
eOpenVaultDialog,
eCloseVaultDialog,
2020-03-14 12:13:00 +05:00
refreshNotesPage,
2020-03-10 23:19:16 +05:00
} from '../../services/events';
2020-03-03 15:25:40 +05:00
import {openEditorAnimation} from '../../utils/animations';
2020-03-03 15:33:33 +05:00
import {ACTIONS} from '../../provider/actions';
2020-03-14 12:59:52 +05:00
import {Toast} from '../Toast';
2020-03-14 13:37:07 +05:00
import {updateEvent} from '../DialogManager/recievers';
2020-03-10 23:19:16 +05:00
2020-03-03 15:37:48 +05:00
const passInputRef = createRef();
2020-03-10 23:19:16 +05:00
const confirmPassRef = createRef();
2020-01-17 21:05:38 +05:00
export class VaultDialog extends Component {
constructor(props) {
super(props);
this.state = {
visible: false,
2020-03-10 23:19:16 +05:00
wrongPassword: false,
note: {},
vault: false,
locked: true,
permanant: false,
goToEditor: false,
share: false,
passwordsDontMatch: false,
2020-03-14 12:13:00 +05:00
deleteNote: false,
2020-01-17 21:05:38 +05:00
};
this.password = null;
2020-03-17 15:09:15 +05:00
this.confirmPassword = null;
2020-01-17 21:05:38 +05:00
}
2020-01-17 00:23:16 +05:00
2020-03-10 23:19:16 +05:00
componentDidMount() {
eSubscribeEvent(eOpenVaultDialog, this.open);
eSubscribeEvent(eCloseVaultDialog, this.close);
}
componentWillUnmount() {
eUnSubscribeEvent(eOpenVaultDialog, this.open);
eUnSubscribeEvent(eCloseVaultDialog, this.close);
}
open = ({
item,
novault,
locked,
permanant = false,
goToEditor = false,
share = false,
2020-03-14 12:13:00 +05:00
deleteNote = false,
2020-03-10 23:19:16 +05:00
}) => {
2020-01-17 21:05:38 +05:00
this.setState({
visible: true,
2020-03-10 23:19:16 +05:00
note: item,
novault: novault,
locked,
permanant,
goToEditor,
share,
2020-03-14 12:13:00 +05:00
deleteNote,
2020-01-17 21:05:38 +05:00
});
};
2020-03-03 15:33:33 +05:00
2020-03-10 23:19:16 +05:00
close = () => {
2020-03-03 15:33:33 +05:00
updateEvent({type: ACTIONS.NOTES});
2020-03-02 13:52:09 +05:00
this.setState({
visible: false,
2020-03-10 23:19:16 +05:00
note: {},
locked: false,
permanant: false,
goToEditor: false,
share: false,
novault: false,
2020-03-14 12:13:00 +05:00
deleteNote: false,
2020-03-02 13:52:09 +05:00
});
2020-01-17 21:05:38 +05:00
};
onPress = async () => {
2020-03-10 23:19:16 +05:00
if (!this.state.novault) {
if (this.password.length < 3) {
2020-03-14 12:59:52 +05:00
ToastEvent.show('Password too short', 'error', 'local');
2020-03-10 23:19:16 +05:00
return;
}
2020-03-17 15:09:15 +05:00
if (this.password !== this.confirmPassword) {
2020-03-14 12:59:52 +05:00
ToastEvent.show('Passwords do not match', 'error', 'local');
2020-03-17 15:09:15 +05:00
this.setState({
passwordsDontMatch: true,
});
2020-03-10 23:19:16 +05:00
return;
}
2020-03-17 15:09:15 +05:00
this._createVault();
2020-03-10 23:19:16 +05:00
} else if (this.state.locked) {
if (!this.password || this.password.trim() === 0) {
2020-03-14 12:59:52 +05:00
ToastEvent.show('Password is invalid', 'error', 'local');
2020-03-14 12:13:00 +05:00
this.setState({
wrongPassword: true,
});
2020-03-03 15:44:31 +05:00
return;
2020-03-10 23:19:16 +05:00
} else {
db.vault
.unlock(this.password)
.then(async () => {
2020-03-14 12:13:00 +05:00
this.setState({
wrongPassword: false,
});
2020-03-10 23:19:16 +05:00
if (this.state.note.locked) {
await this._unlockNote();
} else {
await this._lockNote();
}
})
.catch(e => {
this._takeErrorAction(e);
});
2020-01-17 21:05:38 +05:00
}
2020-03-10 23:19:16 +05:00
}
};
async _lockNote() {
if (!this.password || this.password.trim() === 0) {
2020-03-14 12:59:52 +05:00
ToastEvent.show('Password is invalid', 'error', 'local');
2020-03-10 23:19:16 +05:00
return;
} else {
db.vault.add(this.state.note.id).then(e => {
this.close();
});
}
}
2020-03-03 15:33:33 +05:00
2020-03-10 23:19:16 +05:00
async _unlockNote() {
if (!this.password || this.password.trim() === 0) {
2020-03-14 12:59:52 +05:00
ToastEvent.show('Password is invalid', 'error', 'local');
2020-03-10 23:19:16 +05:00
return;
} else {
if (this.state.permanant) {
this._permanantUnlock();
} else {
await this._openNote();
2020-01-17 21:05:38 +05:00
}
2020-03-10 23:19:16 +05:00
}
}
async _openNote() {
2020-03-14 12:13:00 +05:00
db.vault
.open(this.state.note.id, this.password)
.then(async () => {
if (this.state.goToEditor) {
this._openInEditor(note);
} else if (this.state.share) {
this._shareNote(note);
} else if (this.state.deleteNote) {
await this._deleteNote();
}
})
.catch(e => {
this._takeErrorAction(e);
});
}
async _deleteNote() {
await db.notes.delete(this.state.note.id);
updateEvent({type: ACTIONS.NOTES});
updateEvent({type: ACTIONS.FAVORITES});
eSendEvent(refreshNotesPage);
this.close();
2020-03-14 12:59:52 +05:00
ToastEvent.show('Note deleted', 'success', 'local');
2020-03-10 23:19:16 +05:00
}
async _createVault() {
await db.vault.create(this.password);
if (this.state.note && this.state.note.id && !this.state.note.locked) {
await db.vault.add(this.state.note.id);
this.close();
2020-03-14 12:59:52 +05:00
ToastEvent.show('Note added to vault', 'success', 'local');
2020-03-10 23:19:16 +05:00
}
}
_permanantUnlock() {
db.vault
.remove(this.state.note.id, this.password)
.then(() => {
this.close();
})
.catch(e => {
this._takeErrorAction(e);
});
}
_openInEditor(note) {
eSendEvent(eOnLoadNote, note);
if (!DDS.isTab) {
openEditorAnimation();
}
ToastEvent.show('Note unlocked', 'success');
this.close();
}
_shareNote(note) {
let m = `${note.title}\n \n ${note.content.text}`;
Share.open({
title: 'Share note to',
failOnCancel: false,
message: m,
});
this.close();
}
_takeErrorAction(e) {
if (e.message === db.vault.ERRORS.wrongPassword) {
2020-03-14 12:59:52 +05:00
ToastEvent.show('Password is incorrect', 'error', 'local');
2020-03-10 23:19:16 +05:00
this.setState({
wrongPassword: true,
});
return;
2020-01-17 21:05:38 +05:00
} else {
2020-03-10 23:19:16 +05:00
console.log('ERROR', e.message);
2020-01-17 21:05:38 +05:00
}
2020-03-10 23:19:16 +05:00
}
2020-01-17 21:05:38 +05:00
render() {
2020-03-10 23:19:16 +05:00
const {colors} = this.props;
const {
note,
visible,
wrongPassword,
passwordsDontMatch,
novault,
locked,
permanant,
goToEditor,
share,
} = this.state;
2020-01-17 21:05:38 +05:00
return (
2020-03-03 15:37:48 +05:00
<Modal
onShow={() => {
passInputRef.current?.focus();
}}
visible={visible}
transparent={true}
onRequestClose={this.close}>
2019-12-07 08:41:48 +05:00
<View
style={{
2020-01-17 21:05:38 +05:00
width: '100%',
height: '100%',
backgroundColor: colors.night
? 'rgba(255,255,255,0.3)'
: 'rgba(0,0,0,0.3)',
justifyContent: 'center',
alignItems: 'center',
2019-12-07 08:41:48 +05:00
}}>
<View
style={{
2020-01-17 21:05:38 +05:00
...getElevation(5),
width: '80%',
maxHeight: 350,
borderRadius: 5,
backgroundColor: colors.bg,
paddingHorizontal: ph,
paddingVertical: pv,
2019-12-07 08:41:48 +05:00
}}>
2020-01-17 21:05:38 +05:00
<View
2019-12-07 08:41:48 +05:00
style={{
2020-01-17 21:05:38 +05:00
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
2019-12-07 08:41:48 +05:00
}}>
2020-01-17 21:05:38 +05:00
<Icon name="shield" color={colors.accent} size={SIZE.lg} />
<Text
style={{
color: colors.accent,
fontFamily: WEIGHT.bold,
marginLeft: 5,
fontSize: SIZE.md,
}}>
2020-03-10 23:19:16 +05:00
{!novault
? 'Create vault'
: note.locked
2020-03-14 12:13:00 +05:00
? this.state.deleteNote
? 'Delete note'
: this.state.share
? 'Share note'
: this.state.goToEditor
? 'Unlock note'
: 'Unlock note'
: 'Lock note'}
2020-01-17 21:05:38 +05:00
</Text>
</View>
2019-12-07 08:41:48 +05:00
2020-01-17 21:05:38 +05:00
<Text
2020-01-05 18:03:40 +05:00
style={{
2020-01-17 21:05:38 +05:00
color: colors.icon,
2020-01-05 18:03:40 +05:00
fontFamily: WEIGHT.regular,
2020-01-17 21:05:38 +05:00
textAlign: 'center',
fontSize: SIZE.sm - 1,
2020-03-10 23:19:16 +05:00
flexWrap: 'wrap',
maxWidth: '90%',
alignSelf: 'center',
2020-01-17 21:05:38 +05:00
marginTop: 10,
}}>
2020-03-10 23:19:16 +05:00
{!novault
? 'Set a password to create vault'
: permanant
? 'Enter password to remove note from vault.'
2020-01-17 21:05:38 +05:00
: note.locked
2020-03-14 12:13:00 +05:00
? this.state.deleteNote
? 'Unlock note to delete it.'
: this.state.share
? 'Unlock note to share it.'
: this.state.goToEditor
? 'Unlock note to open it in editor'
: 'Enter vault password to unlock note.'
2020-03-14 12:59:52 +05:00
: 'Enter vault password to lock note.'}
2020-01-17 21:05:38 +05:00
</Text>
2020-01-05 18:03:40 +05:00
2020-03-10 23:19:16 +05:00
{note.locked || locked || permanant ? (
2019-12-07 08:41:48 +05:00
<TextInput
2020-03-03 15:37:48 +05:00
ref={passInputRef}
2019-12-07 08:41:48 +05:00
style={{
padding: pv - 5,
borderWidth: 1.5,
2020-03-10 23:19:16 +05:00
borderColor: this.state.wrongPassword
? colors.errorText
: colors.nav,
2019-12-07 08:41:48 +05:00
paddingHorizontal: ph,
borderRadius: 5,
2020-01-17 21:05:38 +05:00
marginTop: 10,
2019-12-07 08:41:48 +05:00
fontSize: SIZE.sm,
fontFamily: WEIGHT.regular,
}}
2020-01-17 21:05:38 +05:00
onChangeText={value => {
2020-03-03 15:33:33 +05:00
this.password = value;
2020-01-17 21:05:38 +05:00
}}
secureTextEntry
2019-12-07 08:41:48 +05:00
placeholder="Password"
placeholderTextColor={colors.icon}
/>
2020-01-17 21:05:38 +05:00
) : null}
2019-12-07 08:41:48 +05:00
2020-03-10 23:19:16 +05:00
{!novault ? (
2020-01-17 21:05:38 +05:00
<View>
<TextInput
2020-03-10 23:19:16 +05:00
ref={passInputRef}
2020-01-17 21:05:38 +05:00
style={{
padding: pv - 5,
borderWidth: 1.5,
2020-03-10 23:19:16 +05:00
borderColor: passwordsDontMatch
? colors.errorText
: colors.nav,
2020-01-17 21:05:38 +05:00
paddingHorizontal: ph,
borderRadius: 5,
fontSize: SIZE.sm,
fontFamily: WEIGHT.regular,
}}
2020-03-10 23:19:16 +05:00
onChangeText={value => {
this.password = value;
}}
secureTextEntry
2020-01-17 21:05:38 +05:00
placeholder="Password"
placeholderTextColor={colors.icon}
/>
2019-12-07 08:41:48 +05:00
2020-01-17 21:05:38 +05:00
<TextInput
2020-03-10 23:19:16 +05:00
ref={confirmPassRef}
2020-01-17 21:05:38 +05:00
style={{
padding: pv - 5,
borderWidth: 1.5,
2020-03-10 23:19:16 +05:00
borderColor: passwordsDontMatch
? colors.errorText
: colors.nav,
2020-01-17 21:05:38 +05:00
paddingHorizontal: ph,
borderRadius: 5,
fontSize: SIZE.sm,
fontFamily: WEIGHT.regular,
marginTop: 10,
}}
2020-03-10 23:19:16 +05:00
secureTextEntry
onChangeText={value => {
2020-03-17 15:09:15 +05:00
this.confirmPassword = value;
2020-03-10 23:19:16 +05:00
if (value !== this.password) {
this.setState({
passwordsDontMatch: true,
});
} else {
this.setState({
passwordsDontMatch: false,
});
}
2020-01-17 21:05:38 +05:00
}}
2020-03-10 23:19:16 +05:00
placeholder="Confirm password"
2020-01-17 21:05:38 +05:00
placeholderTextColor={colors.icon}
/>
</View>
2020-03-10 23:19:16 +05:00
) : null}
2020-01-05 18:03:40 +05:00
2020-01-17 21:05:38 +05:00
<View
2019-12-07 08:41:48 +05:00
style={{
2020-01-17 21:05:38 +05:00
justifyContent: 'space-around',
2019-12-07 08:41:48 +05:00
alignItems: 'center',
2020-01-17 21:05:38 +05:00
flexDirection: 'row',
marginTop: 20,
2019-12-07 08:41:48 +05:00
}}>
2020-01-17 21:05:38 +05:00
<TouchableOpacity
activeOpacity={opacity}
onPress={this.onPress}
2020-03-10 23:19:16 +05:00
secureTextEntry
2019-12-07 08:41:48 +05:00
style={{
2020-01-17 21:05:38 +05:00
paddingVertical: pv,
paddingHorizontal: ph,
borderRadius: 5,
width: '45%',
justifyContent: 'center',
alignItems: 'center',
borderColor: colors.accent,
backgroundColor: colors.accent,
borderWidth: 1,
2019-12-07 08:41:48 +05:00
}}>
2020-01-17 21:05:38 +05:00
<Text
style={{
fontFamily: WEIGHT.medium,
color: 'white',
fontSize: SIZE.sm,
}}>
2020-03-14 12:13:00 +05:00
{note.locked
? this.state.deleteNote
? 'Delete'
: this.state.share
? 'Share '
: this.state.goToEditor
? 'Open'
: 'Unlock'
: 'Lock'}
2020-01-17 21:05:38 +05:00
</Text>
</TouchableOpacity>
2019-12-07 08:41:48 +05:00
2020-01-17 21:05:38 +05:00
<TouchableOpacity
activeOpacity={opacity}
onPress={this.close}
2019-12-07 08:41:48 +05:00
style={{
2020-01-17 21:05:38 +05:00
paddingVertical: pv,
paddingHorizontal: ph,
borderRadius: 5,
width: '45%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: colors.nav,
2019-12-07 08:41:48 +05:00
}}>
2020-01-17 21:05:38 +05:00
<Text
style={{
fontFamily: WEIGHT.medium,
color: colors.icon,
fontSize: SIZE.sm,
}}>
Cancel
</Text>
</TouchableOpacity>
</View>
2019-12-07 08:41:48 +05:00
</View>
</View>
2020-03-14 12:59:52 +05:00
<Toast context="local" />
2020-01-17 21:05:38 +05:00
</Modal>
);
}
}