update dialog ui similar to desktop app

This commit is contained in:
ammarahm-ed
2021-11-08 15:06:46 +05:00
parent a625dab636
commit 6d2d1dd74a
15 changed files with 494 additions and 411 deletions

View File

@@ -1,4 +1,5 @@
import React, {createRef} from 'react';
import {View} from 'react-native';
import {Actions} from '../../provider/Actions';
import {useMenuStore} from '../../provider/stores';
import {
@@ -119,25 +120,31 @@ export class AddTopicDialog extends React.Component {
paragraph={
this.toEdit
? 'Edit title of the topic'
: 'Add a new topic to ' + this.notebook.title
: 'Create a new topic in ' + this.notebook.title
}
padding={12}
/>
<Seperator half />
<Input
fwdRef={this.titleRef}
onChangeText={value => {
this.title = value;
}}
blurOnSubmit={false}
defaultValue={this.toEdit ? this.toEdit.title : null}
placeholder="Enter title of topic"
onSubmit={() => this.addNewTopic()}
returnKeyLabel="Done"
returnKeyType="done"
/>
<View
style={{
paddingHorizontal: 12
}}>
<Input
fwdRef={this.titleRef}
onChangeText={value => {
this.title = value;
}}
blurOnSubmit={false}
defaultValue={this.toEdit ? this.toEdit.title : null}
placeholder="Enter title of topic"
onSubmit={() => this.addNewTopic()}
returnKeyLabel="Done"
returnKeyType="done"
/>
</View>
<DialogButtons
positiveTitle={this.toEdit ? 'Save' : 'Add'}
positiveTitle={this.toEdit ? 'Save' : 'Create'}
onPressNegative={() => this.close()}
onPressPositive={() => this.addNewTopic()}
loading={this.state.loading}

View File

@@ -7,8 +7,9 @@ import {
StyleSheet,
TouchableOpacity
} from 'react-native';
import { useTracked } from '../../provider';
import {useTracked} from '../../provider';
import useIsFloatingKeyboard from '../../utils/use-is-floating-keyboard';
import {BouncingView} from '../ActionSheetComponent/BouncingView';
const BaseDialog = ({
visible,
@@ -25,7 +26,7 @@ const BaseDialog = ({
}) => {
const [state, dispatch] = useTracked();
const floating = useIsFloatingKeyboard();
return (
<Modal
visible={visible}
@@ -41,26 +42,36 @@ const BaseDialog = ({
onRequestClose={onRequestClose}>
<SafeAreaView
style={{
backgroundColor:background? background : transparent
backgroundColor: background
? background
: transparent
? 'transparent'
: 'rgba(0,0,0,0.3)',
: 'rgba(0,0,0,0.3)'
}}>
<KeyboardAvoidingView
enabled={!floating && Platform.OS === 'ios'}
behavior="padding"
style={[
styles.backdrop,
{
justifyContent: centered ? 'center' : bottom ? 'flex-end' : 'flex-start',
},
]}>
<TouchableOpacity
behavior="padding">
<BouncingView
duration={400}
style={[
styles.backdrop,
{
justifyContent: centered
? 'center'
: bottom
? 'flex-end'
: 'flex-start'
}
]}>
<TouchableOpacity
onPress={onRequestClose}
style={styles.overlayButton}
/>
{premium}
{children}
{children}
</BouncingView>
</KeyboardAvoidingView>
</SafeAreaView>
</Modal>
@@ -72,13 +83,13 @@ const styles = StyleSheet.create({
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
alignItems: 'center'
},
overlayButton: {
width: '100%',
height: '100%',
position: 'absolute',
},
}
});
export default BaseDialog;

View File

@@ -20,7 +20,13 @@ const DialogButtons = ({
const {colors} = state;
return (
<View style={styles.container}>
<View style={[styles.container,{
backgroundColor:colors.nav,
height:60,
borderBottomRightRadius:10,
borderBottomLeftRadius:10,
paddingHorizontal:12
}]}>
{loading ? (
<ActivityIndicator color={colors.accent} size={SIZE.lg} />
) : doneText ? (
@@ -50,6 +56,7 @@ const DialogButtons = ({
fontSize={SIZE.md}
testID={notesnook.ids.default.dialog.no}
type="gray"
bold
title={negativeTitle}
/>
{onPressPositive ? (
@@ -60,6 +67,7 @@ const DialogButtons = ({
style={{
marginLeft: 10,
}}
bold
type={positiveType || "transparent"}
title={positiveTitle}
/>

View File

@@ -15,10 +15,9 @@ const DialogContainer = ({width, height, ...restProps}) => {
...getElevation(5),
width: width || DDS.isTab ? 400 : '85%',
maxHeight: height || 450,
borderRadius: 5,
borderRadius: 10,
backgroundColor: colors.bg,
paddingHorizontal: 12,
paddingVertical: 15,
paddingTop: 12,
}}
/>
);

View File

@@ -6,7 +6,7 @@ import {Button} from '../Button';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
const DialogHeader = ({icon, title, paragraph, button, paragraphColor}) => {
const DialogHeader = ({icon, title, paragraph, button, paragraphColor,padding}) => {
const [state, dispatch] = useTracked();
const colors = state.colors;
@@ -17,7 +17,8 @@ const DialogHeader = ({icon, title, paragraph, button, paragraphColor}) => {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
minHeight: 50
minHeight: 50,
paddingHorizontal:padding
}}>
<View
style={{

View File

@@ -116,7 +116,7 @@ const JumpToDialog = ({scrollRef, data, type, screen}) => {
zIndex: 100,
bottom: 20,
maxHeight: '65%',
borderRadius: 5,
borderRadius: 10,
alignSelf: 'center',
padding: 10,
}}>

View File

@@ -450,7 +450,9 @@ const LoginDialog = () => {
title="Logout"
paragraph="All user data on this device will be cleared including any unsynced changes. Do you want to proceed?"
paragraphColor="red"
padding={12}
/>
<Seperator/>
<DialogButtons
negativeTitle="Cancel"
onPressNegative={() => {
@@ -482,7 +484,7 @@ const LoginDialog = () => {
<BaseDialog
visible={true}
transparent={current.showLoader}
animation="slide"
animation="fade"
onRequestClose={() => {
if (!current.showLoader) {
setStatus(null);

View File

@@ -36,6 +36,7 @@ import BaseDialog from '../Dialog/base-dialog';
import DialogButtons from '../Dialog/dialog-buttons';
import DialogContainer from '../Dialog/dialog-container';
import DialogHeader from '../Dialog/dialog-header';
import Seperator from '../Seperator';
import Paragraph from '../Typography/Paragraph';
const primaryWebView = createRef();
@@ -272,7 +273,9 @@ const MergeEditor = () => {
<DialogHeader
title="Apply Changes"
paragraph="Apply selected changes to note?"
padding={12}
/>
<Seperator/>
<DialogButtons
positiveTitle="Apply"
negativeTitle="Cancel"

View File

@@ -26,7 +26,7 @@ import {useUserStore} from '../../provider/stores';
const features = [
{
title: 'Unlimited attachments'
title: 'Unlimited file & image attachments'
},
{
title: 'Unlimited storage'

View File

@@ -76,13 +76,7 @@ class RecoveryKeyDialog extends React.Component {
if (this.signup) {
this.signup = false;
setTimeout(() => {
eSendEvent(eOpenResultDialog, {
title: 'Welcome to your private\nnote taking haven',
paragraph:
'Please confirm your email to encrypt and sync all your notes.',
icon: 'check',
button: 'Start taking notes'
});
eSendEvent(eOpenResultDialog);
}, 500);
}
};

View File

@@ -0,0 +1,56 @@
import React from 'react';
import {View} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {SIZE} from '../../utils/SizeUtils';
import Paragraph from '../Typography/Paragraph';
export const ProFeatures = () => {
const [state, dispatch] = useTracked();
const {colors} = state;
return (
<>
{[
{
title: 'Unlimited notes & notebooks',
icon: 'notebook'
},
{
title: 'Unlimited file & image attachments',
icon: 'attachment'
},
{
title: 'Lock any note with password',
icon: 'shield-outline'
},
{
title: 'Rich text editing with markdown',
icon: 'pencil'
}
].map(item => (
<View
style={{
flexDirection: 'row',
width: '100%',
height: 40,
paddingHorizontal: 12,
marginBottom: 10,
alignItems: 'center',
borderRadius: 5
}}>
<Icon size={SIZE.md} color={colors.accent} name={item.icon} />
<Paragraph style={{marginLeft: 5}}>{item.title}</Paragraph>
</View>
))}
<Paragraph
onPress={() => {}}
size={SIZE.xs + 2}
style={{
textDecorationLine: 'underline',
color: colors.icon
}}>
See all features included in Notesnook Pro
</Paragraph>
</>
);
};

View File

@@ -1,6 +1,5 @@
import React, { useEffect, useState } from 'react';
import { View } from 'react-native';
import { WELCOME_SVG } from '../../assets/images/assets';
import { useTracked } from '../../provider';
import { DDS } from '../../services/DeviceDetection';
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
@@ -9,15 +8,15 @@ import { eCloseResultDialog, eOpenResultDialog } from '../../utils/Events';
import { ph, SIZE } from '../../utils/SizeUtils';
import { Button } from '../Button';
import BaseDialog from '../Dialog/base-dialog';
import { SvgToPngView } from '../ListPlaceholders';
import Seperator from '../Seperator';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import { ProFeatures } from './pro-features';
const ResultDialog = () => {
const [state, dispatch] = useTracked();
const {colors} = state;
const [visible, setVisible] = useState(false);
const [visible, setVisible] = useState(true);
const [dialogData, setDialogData] = useState({
title: 'Thank you for signing up!',
paragraph:
@@ -49,20 +48,13 @@ const ResultDialog = () => {
...getElevation(5),
width: DDS.isTab ? 350 : '85%',
maxHeight: 500,
borderRadius: 5,
borderRadius: 10,
backgroundColor: colors.bg,
paddingHorizontal: ph,
paddingVertical: 20,
justifyContent: 'center',
alignItems: 'center'
}}>
<SvgToPngView
src={WELCOME_SVG(colors.accent)}
color={colors.accent}
width={240}
height={240}
/>
<Heading
size={SIZE.lg}
textBreakStrategy="balanced"
@@ -75,6 +67,7 @@ const ResultDialog = () => {
}}>
{dialogData.title}
</Heading>
<Paragraph
color={colors.icon}
size={SIZE.md}
@@ -86,6 +79,11 @@ const ResultDialog = () => {
}}>
{dialogData.paragraph}
</Paragraph>
<Seperator />
<ProFeatures />
<Seperator />
<Button
title={dialogData.button}

View File

@@ -52,7 +52,7 @@ export const Card = ({color}) => {
<View
style={{
marginLeft: 10,
maxWidth: '75%'
maxWidth: '70%'
}}>
<Paragraph color={colors.icon} size={SIZE.xs + 1}>
{messageBoardState.message}

View File

@@ -1,11 +1,7 @@
import React, {Component, createRef} from 'react';
import {Platform} from 'react-native';
import {
InteractionManager,
TouchableOpacity,
View,
} from 'react-native';
import Clipboard from "@react-native-clipboard/clipboard"
import {InteractionManager, TouchableOpacity, View} from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';
import Share from 'react-native-share';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {notesnook} from '../../../e2e/test.ids';
@@ -16,7 +12,7 @@ import {
eSubscribeEvent,
eUnSubscribeEvent,
sendNoteEditedEvent,
ToastEvent,
ToastEvent
} from '../../services/EventManager';
import Navigation from '../../services/Navigation';
import {getElevation, toTXT} from '../../utils';
@@ -26,7 +22,7 @@ import {
eCloseActionSheet,
eCloseVaultDialog,
eOnLoadNote,
eOpenVaultDialog,
eOpenVaultDialog
} from '../../utils/Events';
import {deleteItems} from '../../utils/functions';
import {tabBarRef} from '../../utils/Refs';
@@ -73,7 +69,7 @@ export class VaultDialog extends Component {
description: null,
clearVault: false,
deleteVault: false,
deleteAll: false,
deleteAll: false
};
this.password = null;
this.confirmPassword = null;
@@ -164,7 +160,7 @@ export class VaultDialog extends Component {
title: data.title,
description: data.description,
clearVault: data.clearVault,
deleteVault: data.deleteVault,
deleteVault: data.deleteVault
});
if (
@@ -179,7 +175,7 @@ export class VaultDialog extends Component {
await this._onPressFingerprintAuth(data.title, data.description);
} else {
this.setState({
visible: true,
visible: true
});
}
};
@@ -190,20 +186,20 @@ export class VaultDialog extends Component {
heading: this.state.title,
message: 'Please wait and do not close the app.',
type: 'success',
context: 'local',
context: 'local'
});
return;
}
Navigation.setRoutesToUpdate([
Navigation.routeNames.NotesPage,
Navigation.routeNames.Favorites,
Navigation.routeNames.Notes,
Navigation.routeNames.Notes
]);
Navigation.setRoutesToUpdate([
Navigation.routeNames.Notes,
Navigation.routeNames.Favorites,
Navigation.routeNames.NotesPage,
Navigation.routeNames.Notebook,
Navigation.routeNames.Notebook
]);
this.password = null;
this.confirmPassword = null;
@@ -216,7 +212,7 @@ export class VaultDialog extends Component {
share: false,
novault: false,
deleteNote: false,
passwordsDontMatch: false,
passwordsDontMatch: false
});
};
@@ -234,7 +230,7 @@ export class VaultDialog extends Component {
heading: 'Password not entered',
message: 'Enter a password for the vault and try again.',
type: 'error',
context: 'local',
context: 'local'
});
return;
}
@@ -243,7 +239,7 @@ export class VaultDialog extends Component {
heading: 'Password too short',
message: 'Password must be longer than 3 characters.',
type: 'error',
context: 'local',
context: 'local'
});
return;
@@ -254,10 +250,10 @@ export class VaultDialog extends Component {
ToastEvent.show({
heading: 'Passwords do not match',
type: 'error',
context: 'local',
context: 'local'
});
this.setState({
passwordsDontMatch: true,
passwordsDontMatch: true
});
return;
}
@@ -265,14 +261,14 @@ export class VaultDialog extends Component {
this._createVault();
} else if (this.state.changePassword) {
this.setState({
loading: true,
loading: true
});
db.vault
.changePassword(this.password, this.newPassword)
.then(result => {
this.setState({
loading: false,
loading: false
});
if (this.state.biometricUnlock) {
this._enrollFingerprint(this.newPassword);
@@ -280,20 +276,20 @@ export class VaultDialog extends Component {
ToastEvent.show({
heading: 'Vault password updated successfully',
type: 'success',
context: 'global',
context: 'global'
});
this.close();
})
.catch(e => {
this.setState({
loading: false,
loading: false
});
if (e.message === db.vault.ERRORS.wrongPassword) {
ToastEvent.show({
heading: 'Incorrect password',
message: 'Please enter the correct password and try again',
type: 'error',
context: 'local',
context: 'local'
});
}
});
@@ -303,10 +299,10 @@ export class VaultDialog extends Component {
heading: 'Incorrect password',
message: 'Please enter the correct password and try again',
type: 'error',
context: 'local',
context: 'local'
});
this.setState({
wrongPassword: true,
wrongPassword: true
});
return;
}
@@ -314,7 +310,7 @@ export class VaultDialog extends Component {
.unlock(this.password)
.then(async () => {
this.setState({
wrongPassword: false,
wrongPassword: false
});
if (this.state.note.locked) {
await this._unlockNote();
@@ -336,7 +332,7 @@ export class VaultDialog extends Component {
deleteVault = async () => {
this.setState({
loading: true,
loading: true
});
try {
let verified = await db.user.verifyPassword(this.password);
@@ -344,7 +340,7 @@ export class VaultDialog extends Component {
await db.vault.delete(this.state.deleteAll);
eSendEvent('vaultUpdated');
this.setState({
loading: false,
loading: false
});
this.close();
} else {
@@ -352,23 +348,23 @@ export class VaultDialog extends Component {
heading: 'Account password incorrect',
message: 'Please enter correct password for your account.',
type: 'error',
context: 'local',
context: 'local'
});
}
} catch (e) {}
this.setState({
loading: false,
loading: false
});
};
clearVault = async () => {
this.setState({
loading: true,
loading: true
});
try {
await db.vault.clear(this.password);
this.setState({
loading: false,
loading: false
});
this.close();
eSendEvent('vaultUpdated');
@@ -377,11 +373,11 @@ export class VaultDialog extends Component {
heading: 'Vault password incorrect',
message: 'Please enter correct password to clear vault.',
type: 'error',
context: 'local',
context: 'local'
});
}
this.setState({
loading: false,
loading: false
});
};
@@ -391,7 +387,7 @@ export class VaultDialog extends Component {
message: 'Incorrect password',
message: 'Please enter the correct password and try again',
type: 'error',
context: 'local',
context: 'local'
});
console.log('returning from here');
return;
@@ -404,10 +400,10 @@ export class VaultDialog extends Component {
ToastEvent.show({
message: 'Note locked successfully',
type: 'error',
context: 'local',
context: 'local'
});
this.setState({
loading: false,
loading: false
});
}
}
@@ -418,7 +414,7 @@ export class VaultDialog extends Component {
heading: 'Incorrect password',
message: 'Please enter the correct password and try again',
type: 'error',
context: 'local',
context: 'local'
});
return;
}
@@ -462,21 +458,21 @@ export class VaultDialog extends Component {
try {
this.setState(
{
loading: true,
loading: true
},
async () => {
try {
await db.vault.unlock(password);
await BiometricService.storeCredentials(password);
this.setState({
loading: false,
loading: false
});
eSendEvent('vaultUpdated');
ToastEvent.show({
heading: 'Biometric unlocking enabled!',
message: 'Now you can unlock notes in vault with biometrics.',
type: 'success',
context: 'global',
context: 'global'
});
this.close();
} catch (e) {
@@ -485,14 +481,14 @@ export class VaultDialog extends Component {
message:
'Please enter the correct vault password to enable biometrics.',
type: 'error',
context: 'local',
context: 'local'
});
this.setState({
loading: false,
loading: false
});
return;
}
},
}
);
} catch (e) {
this._takeErrorAction(e);
@@ -511,12 +507,12 @@ export class VaultDialog extends Component {
eSendEvent(eClearEditor);
}
this.setState({
loading: false,
loading: false
});
ToastEvent.show({
heading: 'Note added to vault',
type: 'success',
context: 'global',
context: 'global'
});
this.close();
} else {
@@ -524,7 +520,7 @@ export class VaultDialog extends Component {
ToastEvent.show({
heading: 'Vault created successfully',
type: 'success',
context: 'global',
context: 'global'
});
this.close();
}
@@ -537,7 +533,7 @@ export class VaultDialog extends Component {
ToastEvent.show({
heading: 'Note permanantly unlocked.',
type: 'success',
context: 'global',
context: 'global'
});
this.close();
})
@@ -565,7 +561,7 @@ export class VaultDialog extends Component {
heading: 'Note copied',
type: 'success',
message: 'Note has been copied to clipboard!',
context: 'global',
context: 'global'
});
this.close();
}
@@ -578,7 +574,7 @@ export class VaultDialog extends Component {
await Share.open({
heading: 'Share note',
failOnCancel: false,
message: text,
message: text
});
} catch (e) {}
}
@@ -587,13 +583,13 @@ export class VaultDialog extends Component {
if (e.message === db.vault.ERRORS.wrongPassword) {
this.setState({
wrongPassword: true,
visible: true,
visible: true
});
setTimeout(() => {
ToastEvent.show({
heading: 'Incorrect password',
type: 'error',
context: 'local',
context: 'local'
});
}, 500);
@@ -608,14 +604,14 @@ export class VaultDialog extends Component {
ToastEvent.show({
heading: 'Biometric unlocking disabled!',
type: 'success',
context: 'global',
context: 'global'
});
} catch (e) {
ToastEvent.show({
heading: 'Failed to disable Biometric unlocking.',
message: e.message,
type: 'success',
context: 'global',
context: 'global'
});
}
};
@@ -624,7 +620,7 @@ export class VaultDialog extends Component {
try {
let credentials = await BiometricService.getCredentials(
title || this.state.title,
description || this.state.description,
description || this.state.description
);
if (credentials?.password) {
@@ -634,7 +630,7 @@ export class VaultDialog extends Component {
eSendEvent(eCloseActionSheet);
await sleep(300);
this.setState({
visible: true,
visible: true
});
}
} catch (e) {}
@@ -659,7 +655,7 @@ export class VaultDialog extends Component {
copyNote,
loading,
deleteVault,
clearVault,
clearVault
} = this.state;
if (!visible) return null;
@@ -676,162 +672,166 @@ export class VaultDialog extends Component {
style={{
...getElevation(5),
width: DDS.isTab ? 350 : '85%',
borderRadius: 5,
borderRadius: 10,
backgroundColor: colors.bg,
paddingHorizontal: ph,
paddingVertical: 15,
paddingTop: 12
}}>
<DialogHeader
title={this.state.title}
paragraph={this.state.description}
icon="shield"
padding={12}
/>
<Seperator half />
{(novault ||
changePassword ||
this.state.clearVault ||
this.state.deleteVault) &&
!this.state.revokeFingerprintAccess ? (
<>
<Input
fwdRef={passInputRef}
editable={!loading}
autoCapitalize="none"
testID={notesnook.ids.dialogs.vault.pwd}
onChangeText={value => {
this.password = value;
}}
marginBottom={
!this.state.biometricUnlock ||
!this.state.isBiometryEnrolled ||
!novault ||
changePassword
? 0
: 10
}
onSubmit={() => {
changePassword
? changePassInputRef.current?.focus()
: this.onPress;
}}
autoCompleteType="password"
returnKeyLabel={changePassword ? 'Next' : this.state.title}
returnKeyType={changePassword ? 'next' : 'done'}
secureTextEntry
placeholder={changePassword ? 'Current password' : 'Password'}
/>
{!this.state.biometricUnlock ||
!this.state.isBiometryEnrolled ||
!novault ||
changePassword ? null : (
<Button
onPress={() =>
this._onPressFingerprintAuth('Unlock note', '')
<View
style={{
paddingHorizontal: 12
}}>
{(novault ||
changePassword ||
this.state.clearVault ||
this.state.deleteVault) &&
!this.state.revokeFingerprintAccess ? (
<>
<Input
fwdRef={passInputRef}
editable={!loading}
autoCapitalize="none"
testID={notesnook.ids.dialogs.vault.pwd}
onChangeText={value => {
this.password = value;
}}
marginBottom={
!this.state.biometricUnlock ||
!this.state.isBiometryEnrolled ||
!novault ||
changePassword
? 0
: 10
}
icon="fingerprint"
width="100%"
title={'Biometric unlock'}
type="shade"
onSubmit={() => {
changePassword
? changePassInputRef.current?.focus()
: this.onPress;
}}
autoCompleteType="password"
returnKeyLabel={changePassword ? 'Next' : this.state.title}
returnKeyType={changePassword ? 'next' : 'done'}
secureTextEntry
placeholder={changePassword ? 'Current password' : 'Password'}
/>
)}
</>
) : null}
{this.state.deleteVault && (
<Button
onPress={() =>
this.setState({
deleteAll: !this.state.deleteAll,
})
}
icon={
this.state.deleteAll
? 'check-circle-outline'
: 'checkbox-blank-circle-outline'
}
style={{
marginTop:10
}}
width="100%"
title={'Delete all notes'}
type="errorShade"
/>
)}
{!this.state.biometricUnlock ||
!this.state.isBiometryEnrolled ||
!novault ||
changePassword ? null : (
<Button
onPress={() =>
this._onPressFingerprintAuth('Unlock note', '')
}
icon="fingerprint"
width="100%"
title={'Biometric unlock'}
type="transparent"
/>
)}
</>
) : null}
{changePassword ? (
<>
<Seperator half/>
<Input
ref={changePassInputRef}
editable={!loading}
testID={notesnook.ids.dialogs.vault.changePwd}
autoCapitalize="none"
onChangeText={value => {
this.newPassword = value;
{this.state.deleteVault && (
<Button
onPress={() =>
this.setState({
deleteAll: !this.state.deleteAll
})
}
icon={
this.state.deleteAll
? 'check-circle-outline'
: 'checkbox-blank-circle-outline'
}
style={{
marginTop: 10
}}
autoCompleteType="password"
onSubmit={this.onPress}
returnKeyLabel="Change"
returnKeyType="done"
secureTextEntry
placeholder={'New password'}
width="100%"
title={'Delete all notes'}
type="errorShade"
/>
</>
) : null}
)}
{!novault ? (
<View>
<Input
fwdRef={passInputRef}
autoCapitalize="none"
testID={notesnook.ids.dialogs.vault.pwd}
onChangeText={value => {
this.password = value;
}}
autoCompleteType="password"
returnKeyLabel="Next"
returnKeyType="next"
secureTextEntry
onSubmit={() => {
confirmPassRef.current?.focus();
}}
placeholder="Password"
/>
{changePassword ? (
<>
<Seperator half />
<Input
ref={changePassInputRef}
editable={!loading}
testID={notesnook.ids.dialogs.vault.changePwd}
autoCapitalize="none"
onChangeText={value => {
this.newPassword = value;
}}
autoCompleteType="password"
onSubmit={this.onPress}
returnKeyLabel="Change"
returnKeyType="done"
secureTextEntry
placeholder={'New password'}
/>
</>
) : null}
<Input
fwdRef={confirmPassRef}
autoCapitalize="none"
testID={notesnook.ids.dialogs.vault.pwdAlt}
secureTextEntry
validationType="confirmPassword"
customValidator={() => this.password}
errorMessage="Passwords do not match."
onErrorCheck={e => null}
marginBottom={0}
autoCompleteType="password"
returnKeyLabel="Create"
returnKeyType="done"
onChangeText={value => {
this.confirmPassword = value;
if (value !== this.password) {
this.setState({
passwordsDontMatch: true,
});
} else {
this.setState({
passwordsDontMatch: false,
});
}
}}
onSubmit={this.onPress}
placeholder="Confirm password"
/>
</View>
) : null}
{!novault ? (
<View>
<Input
fwdRef={passInputRef}
autoCapitalize="none"
testID={notesnook.ids.dialogs.vault.pwd}
onChangeText={value => {
this.password = value;
}}
autoCompleteType="password"
returnKeyLabel="Next"
returnKeyType="next"
secureTextEntry
onSubmit={() => {
confirmPassRef.current?.focus();
}}
placeholder="Password"
/>
{this.state.biometricUnlock &&
<Input
fwdRef={confirmPassRef}
autoCapitalize="none"
testID={notesnook.ids.dialogs.vault.pwdAlt}
secureTextEntry
validationType="confirmPassword"
customValidator={() => this.password}
errorMessage="Passwords do not match."
onErrorCheck={e => null}
marginBottom={0}
autoCompleteType="password"
returnKeyLabel="Create"
returnKeyType="done"
onChangeText={value => {
this.confirmPassword = value;
if (value !== this.password) {
this.setState({
passwordsDontMatch: true
});
} else {
this.setState({
passwordsDontMatch: false
});
}
}}
onSubmit={this.onPress}
placeholder="Confirm password"
/>
</View>
) : null}
{this.state.biometricUnlock &&
!this.state.isBiometryEnrolled &&
novault ? (
<Paragraph>
@@ -839,27 +839,28 @@ export class VaultDialog extends Component {
</Paragraph>
) : null}
{this.state.isBiometryAvailable &&
!this.state.fingerprintAccess &&
!this.state.clearVault &&
!this.state.deleteVault &&
((!this.state.biometricUnlock && !changePassword) || !novault) ? (
<Button
onPress={() => {
console.log(this.state.biometricUnlock)
this.setState({
biometricUnlock: !this.state.biometricUnlock,
});
}}
style={{
marginTop: 10,
}}
icon="fingerprint"
width="100%"
title="Biometric unlocking"
type={this.state.biometricUnlock ? "shade" : 'grayBg'}
/>
) : null}
{this.state.isBiometryAvailable &&
!this.state.fingerprintAccess &&
!this.state.clearVault &&
!this.state.deleteVault &&
((!this.state.biometricUnlock && !changePassword) || !novault) ? (
<Button
onPress={() => {
console.log(this.state.biometricUnlock);
this.setState({
biometricUnlock: !this.state.biometricUnlock
});
}}
style={{
marginTop: 10
}}
icon="fingerprint"
width="100%"
title="Biometric unlocking"
type={this.state.biometricUnlock ? 'transparent' : 'gray'}
/>
) : null}
</View>
<DialogButtons
onPressNegative={this.close}

View File

@@ -391,8 +391,8 @@ const SectionHeader = ({title, collapsed, setCollapsed}) => {
alignSelf: 'center',
marginBottom: 5,
marginTop: 5,
borderBottomWidth:1,
borderBottomColor:colors.nav
borderBottomWidth: 1,
borderBottomColor: colors.nav
}}>
{collapsed ? (
<Paragraph
@@ -437,9 +437,12 @@ const AccoutLogoutSection = () => {
justifyContent: 'center',
alignItems: 'center'
}}>
<Heading color={colors.pri} size={SIZE.md}>
<Heading color={colors.pri} size={SIZE.lg}>
Logging out
</Heading>
<Paragraph color={colors.icon}>
Please wait while log out and clear app data.
</Paragraph>
<View
style={{
flexDirection: 'row',
@@ -459,7 +462,9 @@ const AccoutLogoutSection = () => {
<DialogHeader
title="Logout"
paragraph="Clear all your data and reset the app."
padding={12}
/>
<Seperator />
<DialogButtons
positiveTitle="Logout"
negativeTitle="Cancel"
@@ -493,65 +498,57 @@ const AccoutLogoutSection = () => {
<DialogContainer>
<DialogHeader
title="Delete account"
paragraph="Your account will be deleted and all your data will be removed
paragraph="All your data will be removed
permanantly. Make sure you have saved backup of your notes. This action is IRREVERSIBLE."
paragraphColor={colors.red}
padding={12}
/>
<Input
placeholder="Enter account password"
fwdRef={pwdInput}
onChangeText={v => {
passwordValue = v;
}}
secureTextEntry={true}
/>
<Seperator half />
<View
style={{
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'flex-end'
paddingHorizontal: 12
}}>
<Button
onPress={() => {
setDeleteAccount(false);
passwordValue = null;
<Input
placeholder="Enter account password"
fwdRef={pwdInput}
onChangeText={v => {
passwordValue = v;
}}
fontSize={SIZE.md}
type="gray"
title="Cancel"
/>
<Button
onPress={async () => {
if (!passwordValue) {
ToastEvent.show({
heading: 'Account Password is required',
type: 'error',
context: 'local'
});
return;
}
try {
await db.user.deleteUser(passwordValue);
} catch (e) {
ToastEvent.show({
heading: 'Failed to delete account',
message: e.message,
type: 'error',
context: 'local'
});
}
close();
}}
fontSize={SIZE.md}
style={{
marginLeft: 10
}}
type="error"
title="Delete"
secureTextEntry={true}
/>
</View>
<DialogButtons
positiveTitle="Delete"
positiveType="errorShade"
onPressPositive={async () => {
if (!passwordValue) {
ToastEvent.show({
heading: 'Account Password is required',
type: 'error',
context: 'local'
});
return;
}
try {
await db.user.deleteUser(passwordValue);
} catch (e) {
ToastEvent.show({
heading: 'Failed to delete account',
message: e.message,
type: 'error',
context: 'local'
});
}
close();
}}
onPressNegative={() => {
setDeleteAccount(false);
passwordValue = null;
}}
/>
</DialogContainer>
<Toast context="local" />
</BaseDialog>
@@ -735,6 +732,10 @@ const SettingsUserSection = () => {
};
const manageSubscription = () => {
if (!user.isEmailConfirmed) {
PremiumService.showVerifyEmailDialog();
return;
}
if (
user.subscription?.type === SUBSCRIPTION_STATUS.PREMIUM_CANCELLED &&
Platform.OS === 'android'
@@ -784,7 +785,7 @@ const SettingsUserSection = () => {
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'row',
paddingBottom: 2.5,
paddingBottom: 4,
borderBottomWidth: 1,
borderColor: colors.accent
}}>
@@ -850,7 +851,7 @@ const SettingsUserSection = () => {
{isExpired
? 'Your subscription has ended.'
: user.subscription?.type === 1
? `Your trial has started`
? `Your free trial has started`
: `Subscribed to Notesnook Pro`}
</Paragraph>
<Paragraph
@@ -861,7 +862,7 @@ const SettingsUserSection = () => {
{user.subscription?.type === 2
? 'You signed up on ' + startDate
: user.subscription?.type === 1
? 'Your trial will end on ' + expiryDate
? 'Your free trial will end on ' + expiryDate
: user.subscription?.type === 6
? subscriptionDaysLeft.time < -3
? 'Your subscription has ended'
@@ -875,8 +876,7 @@ const SettingsUserSection = () => {
</View>
) : null}
{user.isEmailConfirmed &&
user.subscription?.type !== SUBSCRIPTION_STATUS.PREMIUM &&
{user.subscription?.type !== SUBSCRIPTION_STATUS.PREMIUM &&
user.subscription?.type !== SUBSCRIPTION_STATUS.BETA && (
<>
<Seperator />
@@ -888,9 +888,11 @@ const SettingsUserSection = () => {
}}
fontSize={SIZE.md}
title={
user.subscription?.provider === 3 &&
user.subscription?.type ===
SUBSCRIPTION_STATUS.PREMIUM_CANCELLED
!user.isEmailConfirmed
? 'Confirm your email to get 7 days more'
: user.subscription?.provider === 3 &&
user.subscription?.type ===
SUBSCRIPTION_STATUS.PREMIUM_CANCELLED
? 'Manage subscription from desktop app'
: user.subscription?.type ===
SUBSCRIPTION_STATUS.PREMIUM_CANCELLED &&
@@ -965,43 +967,32 @@ const SettingsUserSection = () => {
<DialogHeader
title="Verify it's you"
paragraph="Enter your account password to save your data recovery key."
padding={12}
/>
<Seperator half />
<Input
fwdRef={input}
placeholder="Enter account password"
onChangeText={v => {
passwordVerifyValue = v;
}}
onSubmit={tryVerification}
secureTextEntry={true}
/>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'flex-end'
paddingHorizontal: 12
}}>
<Button
onPress={() => {
setVerifyUser(false);
passwordVerifyValue = null;
<Input
fwdRef={input}
placeholder="Enter account password"
onChangeText={v => {
passwordVerifyValue = v;
}}
fontSize={SIZE.md}
type="gray"
title="Cancel"
/>
<Button
onPress={tryVerification}
fontSize={SIZE.md}
style={{
marginLeft: 10
}}
type="transparent"
title="Verify"
onSubmit={tryVerification}
secureTextEntry={true}
/>
</View>
<DialogButtons
positiveTitle="Verify"
onPressPositive={tryVerification}
onPressNegative={() => {
setVerifyUser(false);
passwordVerifyValue = null;
}}
/>
</DialogContainer>
<Toast context="local" />
</BaseDialog>
@@ -1015,7 +1006,7 @@ const SettingsUserSection = () => {
},
desc: 'Recover your data using the recovery key if your password is lost.'
},
/* {
/* {
name: 'Change password',
func: async () => {
eSendEvent(eOpenLoginDialog, 3);
@@ -1335,7 +1326,7 @@ const SettingsAppearanceSection = () => {
style={{
backgroundColor:
settings.homepage === item.name
? colors.shade
? colors.nav
: 'transparent'
}}
textStyle={{
@@ -1398,17 +1389,17 @@ const SettingsPrivacyAndSecurity = () => {
{
title: 'None',
value: 'none',
desc: 'Disable app lock. Notes will be accessible to anyone who opens the app'
desc: 'Disable app lock. Notes can be accessed by anyone who opens the app'
},
{
title: 'Secure Mode',
value: 'launch',
desc: 'Lock app on launch and keep it unlocked when you switch to other apps.'
desc: 'Locks app on launch and keeps it unlocked when you switch to other apps.'
},
{
title: 'Strict Mode',
value: 'background',
desc: 'Lock app on launch and also when you switch from other apps or background.'
desc: 'Locks app on launch and also when you switch from other apps or background.'
}
];
@@ -1423,7 +1414,7 @@ const SettingsPrivacyAndSecurity = () => {
: 'Enable biometery unlock',
description: vaultStatus.biometryEnrolled
? 'Disable biometric unlocking for notes in vault'
: 'Disable biometric unlocking for notes in vault'
: 'Enable biometric unlocking for notes in vault'
});
};
@@ -1439,48 +1430,60 @@ const SettingsPrivacyAndSecurity = () => {
<DialogHeader
title="App lock mode"
paragraph="Select the level of security you want to enable."
padding={12}
/>
<Seperator />
{modes.map(item => (
<PressableButton
type={
settings.appLockMode === item.value ? 'accent' : 'transparent'
}
onPress={() => {
SettingsService.set('appLockMode', item.value);
}}
customStyle={{
justifyContent: 'flex-start',
alignItems: 'flex-start',
paddingHorizontal: 6,
paddingVertical: 6,
marginTop: 3,
marginBottom: 3
}}
style={{
marginBottom: 10
}}>
<Heading
color={
settings.appLockMode === item.value ? 'white' : colors.pri
<View
style={{
paddingHorizontal: 12
}}>
{modes.map(item => (
<PressableButton
type={
settings.appLockMode === item.value
? 'grayBg'
: 'transparent'
}
style={{maxWidth: '95%'}}
size={SIZE.md}>
{item.title}
</Heading>
<Paragraph
color={
settings.appLockMode === item.value ? 'white' : colors.icon
}
style={{maxWidth: '95%'}}
size={SIZE.sm}>
{item.desc}
</Paragraph>
</PressableButton>
))}
onPress={() => {
SettingsService.set('appLockMode', item.value);
}}
customStyle={{
justifyContent: 'flex-start',
alignItems: 'flex-start',
paddingHorizontal: 6,
paddingVertical: 6,
marginTop: 3,
marginBottom: 3
}}
style={{
marginBottom: 10
}}>
<Heading
color={
settings.appLockMode === item.value
? colors.accent
: colors.pri
}
style={{maxWidth: '95%'}}
size={SIZE.md}>
{item.title}
</Heading>
<Paragraph
color={
settings.appLockMode === item.value
? colors.accent
: colors.icon
}
style={{maxWidth: '95%'}}
size={SIZE.sm}>
{item.desc}
</Paragraph>
</PressableButton>
))}
</View>
<DialogButtons
negativeTitle="Close"
negativeTitle="Done"
onPressNegative={() => {
setAppLockVisible(false);
}}
@@ -1780,11 +1783,11 @@ export const SettingsBackupAndRestore = ({isSheet}) => {
func: async () => {
if (!user || !user?.email) {
ToastEvent.show({
heading:"Login required",
message:"Please login to your account to restore backup",
type:"error",
context:'global'
})
heading: 'Login required',
message: 'Please login to your account to restore backup',
type: 'error',
context: 'global'
});
return;
}
if (isSheet) {