diff --git a/apps/mobile/App.js b/apps/mobile/App.js
index 7aea56c3b..7905d4c2a 100644
--- a/apps/mobile/App.js
+++ b/apps/mobile/App.js
@@ -39,6 +39,7 @@ import Animated, {Easing} from 'react-native-reanimated';
import {useForceUpdate} from './src/views/ListsEditor';
import FastStorage from 'react-native-fast-storage';
import {defaultState} from './src/provider/defaultState';
+import {EditorPosition} from './src/utils/animations';
export const DDS = new DeviceDetectionService();
export const db = new Storage(StorageInterface);
@@ -176,9 +177,9 @@ const App = () => {
} else {
s = JSON.parse(s);
scale.fontScale = s.fontScale;
- console.log(scale.fontScale);
+
updateSize();
- console.log(SIZE.lg);
+
dispatch({type: ACTIONS.SETTINGS, settings: {...s}});
}
dispatch({type: ACTIONS.THEME, colors: newColors});
@@ -367,7 +368,27 @@ const App = () => {
/>
)}
+
+ (editorRef = ref)}
+ style={{
+ width: '100%',
+ height: '100%',
+ position: 'absolute',
+ zIndex: 10,
+ backgroundColor: colors.bg,
+ elevation: 10,
+ transform: [
+ {
+ translateX: EditorPosition,
+ },
+ ],
+ }}>
+
+
+
+
>
diff --git a/apps/mobile/src/components/ActionSheetComponent/index.js b/apps/mobile/src/components/ActionSheetComponent/index.js
index b3b2b9efc..e6390a98a 100644
--- a/apps/mobile/src/components/ActionSheetComponent/index.js
+++ b/apps/mobile/src/components/ActionSheetComponent/index.js
@@ -1,4 +1,4 @@
-import React, {useEffect, useState} from 'react';
+import React, {useEffect, useState, createRef} from 'react';
import {
Dimensions,
StatusBar,
@@ -32,7 +32,7 @@ import NavigationService from '../../services/NavigationService';
const w = Dimensions.get('window').width;
const h = Dimensions.get('window').height;
-let tagsInputRef;
+const tagsInputRef = createRef();
export const ActionSheetComponent = ({
close = () => {},
item,
@@ -42,7 +42,7 @@ export const ActionSheetComponent = ({
columnItems = [],
}) => {
const [state, dispatch] = useTracked();
- const {colors, tags} = state;
+ const {colors, tags, currentEditingNote} = state;
const [focused, setFocused] = useState(false);
const [note, setNote] = useState(
item
@@ -78,14 +78,16 @@ export const ActionSheetComponent = ({
let backPressCount = 0;
const _onSubmit = async () => {
- if (!tagToAdd || tagToAdd === '') return;
-
+ if (!tagToAdd || tagToAdd === '' || tagToAdd.trimStart().length == 0) {
+ ToastEvent.show('Empty Tag', 'success');
+ return;
+ }
let tag = tagToAdd;
if (tag.includes(' ')) {
tag = tag.replace(' ', '_');
}
- tagsInputRef.setNativeProps({
+ tagsInputRef.current?.setNativeProps({
text: '',
});
@@ -116,10 +118,20 @@ export const ActionSheetComponent = ({
setNote({...db.notes.note(note.id).data});
- tagsInputRef.setNativeProps({
+ tagsInputRef.current?.setNativeProps({
text: tagInputValue,
});
}
+ } else if (event.nativeEvent.key === ' ') {
+ _onSubmit();
+ tagsInputRef.current?.setNativeProps({
+ text: '',
+ });
+ } else if (event.nativeE.key === ',') {
+ _onSubmit();
+ tagsInputRef.current?.setNativeProps({
+ text: '',
+ });
}
};
@@ -333,9 +345,14 @@ export const ActionSheetComponent = ({
key={tag}
onPress={async () => {
let oldProps = {...note};
-
- await db.notes.note(note.id).untag(oldProps.tags.indexOf(tag));
- localRefresh(item.type);
+ try {
+ await db.notes
+ .note(note.id)
+ .untag(oldProps.tags[oldProps.tags.indexOf(tag)]);
+ localRefresh(oldProps.type);
+ } catch (e) {
+ localRefresh(oldProps.type);
+ }
}}
style={{
flexDirection: 'row',
@@ -422,7 +439,7 @@ export const ActionSheetComponent = ({
}}
name={rowItem.icon}
size={DDS.isTab ? SIZE.xl : SIZE.lg}
- color={colors.accent}
+ color={rowItem.name === 'Delete' ? colors.errorText : colors.accent}
/>
+ {
+ tagsInputRef.current?.focus();
+ }}
+ style={{
+ position: 'absolute',
+ width: '100%',
+ height: '100%',
+ }}>
{note && note.tags ? note.tags.map(_renderTag) : null}
(tagsInputRef = ref)}
+ ref={tagsInputRef}
placeholderTextColor={colors.icon}
onFocus={() => {
setFocused(true);
diff --git a/apps/mobile/src/components/AddNotebookDialog/index.js b/apps/mobile/src/components/AddNotebookDialog/index.js
index 22033a1e3..ac57f1026 100644
--- a/apps/mobile/src/components/AddNotebookDialog/index.js
+++ b/apps/mobile/src/components/AddNotebookDialog/index.js
@@ -108,33 +108,42 @@ export class AddNotebookDialog extends React.Component {
if (this.currentInputValue) {
this.onSubmit();
}
- let {topics} = this.state;
- let {toEdit} = this.props;
- if (!this.title)
- return ToastEvent.show('Title is required', 'error', 3000, () => {}, '');
- let id = toEdit && toEdit.id ? toEdit.id : null;
+ setTimeout(async () => {
+ let {topics} = this.state;
+ let {toEdit} = this.props;
+ if (!this.title)
+ return ToastEvent.show(
+ 'Title is required',
+ 'error',
+ 3000,
+ () => {},
+ '',
+ );
- if (id) {
- await db.notebooks.add({
- title: this.title,
- description: this.description,
- id: id,
- });
+ let id = toEdit && toEdit.id ? toEdit.id : null;
- await db.notebooks.notebook(id).topics.add(...topics);
- } else {
- await db.notebooks.add({
- title: this.title,
- description: this.description,
- topics,
- id: id,
- });
- }
+ if (id) {
+ await db.notebooks.add({
+ title: this.title,
+ description: this.description,
+ id: id,
+ });
- updateEvent({type: ACTIONS.NOTEBOOKS});
- this.close();
- ToastEvent.show('New notebook added', 'success', 3000, () => {}, '');
+ await db.notebooks.notebook(id).topics.add(...topics);
+ } else {
+ await db.notebooks.add({
+ title: this.title,
+ description: this.description,
+ topics,
+ id: id,
+ });
+ }
+ this.close();
+ updateEvent({type: ACTIONS.NOTEBOOKS});
+
+ ToastEvent.show('New notebook added', 'success', 3000, () => {}, '');
+ }, 100);
};
onSubmit = () => {
@@ -205,6 +214,9 @@ export class AddNotebookDialog extends React.Component {
transparent={true}
animated
animationType="fade"
+ onShow={() => {
+ this.titleRef.focus();
+ }}
onRequestClose={this.close}>
{
@@ -52,6 +53,9 @@ export class AddTopicDialog extends React.Component {
animated
animationType="fade"
transparent={true}
+ onShow={() => {
+ this.titleRef.current?.focus();
+ }}
onRequestClose={() => {
refs = [];
this.close();
@@ -102,6 +106,7 @@ export class AddTopicDialog extends React.Component {
{
+ if (i.type === 'note') {
+ await db.notes.delete(i.id);
+ ToastEvent.show('Notes moved to trash', 'error', 3000);
+ updateEvent({type: i.type});
+ } else if (i.type === 'topic') {
+ await db.notebooks.notebook(i.notebookId).topics.delete(i.title);
+ updateEvent({type: 'notebook'});
+
+ ToastEvent.show('Topics deleted', 'error', 3000);
+ } else if (i.type === 'notebook') {
+ await db.notebooks.delete(i.id);
+ updateEvent({type: i.type});
+ ToastEvent.show('Notebooks moved to trash', 'error', 3000);
+ }
+ });
+
+ updateEvent({type: ACTIONS.CLEAR_SELECTION});
+ updateEvent({type: ACTIONS.SELECTION_MODE, enabled: false});
this.setState({
visible: false,
});
+ if (editing.currentlyEditing) {
+ if (DDS.isTab) {
+ eSendEvent(eCloseFullscreenEditor);
+ eSendEvent(eOnLoadNote, {type: 'new'});
+ } else {
+ NavigationService.goBack();
+ }
+ }
break;
}
case dialogActions.ACTION_EXIT: {
@@ -81,7 +94,7 @@ export class Dialog extends Component {
break;
}
case dialogActions.ACTION_TRASH: {
- db.trash.restore(item.id);
+ await db.trash.restore(i.id);
ToastEvent.show(
item.type.slice(0, 1).toUpperCase() +
item.type.slice(1) +
@@ -89,6 +102,7 @@ export class Dialog extends Component {
'success',
3000,
);
+
updateEvent({type: ACTIONS.TRASH});
this.hide();
break;
@@ -108,8 +122,10 @@ export class Dialog extends Component {
};
show = () => {
+ console.log(history.selectedItemsList.length, 'length');
this.setState({
visible: true,
+ selectedItemsLength: history.selectedItemsList.length,
});
};
hide = () => {
@@ -187,7 +203,11 @@ export class Dialog extends Component {
textAlign: 'center',
marginTop: 10,
}}>
- {paragraph}
+ {this.state.selectedItemsLength > 0
+ ? 'Delete ' +
+ this.state.selectedItemsLength +
+ ' selected items?'
+ : paragraph}
) : null}
diff --git a/apps/mobile/src/components/Menu/index.js b/apps/mobile/src/components/Menu/index.js
index a8476aead..3c742f8fd 100644
--- a/apps/mobile/src/components/Menu/index.js
+++ b/apps/mobile/src/components/Menu/index.js
@@ -30,6 +30,7 @@ import {eSendEvent} from '../../services/eventManager';
import {eOpenModalMenu, eSendSideMenuOverlayRef} from '../../services/events';
import NavigationService from '../../services/NavigationService';
import {timeSince, getElevation, hexToRGBA} from '../../utils/utils';
+import {inputRef} from '../SearchInput';
export const Menu = ({
close = () => {},
@@ -189,7 +190,7 @@ export const Menu = ({
)}
{
item.close === false ? null : close();
-
+ if (item.close) {
+ inputRef.current?.setNativeProps({
+ text: '',
+ });
+ dispatch({type: ACTIONS.SEARCH_RESULTS, results: []});
+ }
item.func();
}}
style={{
diff --git a/apps/mobile/src/components/NoteItem/index.js b/apps/mobile/src/components/NoteItem/index.js
index 11b55ec7c..38b0e45a6 100644
--- a/apps/mobile/src/components/NoteItem/index.js
+++ b/apps/mobile/src/components/NoteItem/index.js
@@ -12,6 +12,7 @@ import {
simpleDialogEvent,
TEMPLATE_TRASH,
} from '../DialogManager';
+import {openEditorAnimation} from '../../utils/animations';
const w = Dimensions.get('window').width;
const h = Dimensions.get('window').height;
@@ -116,14 +117,15 @@ export default class NoteItem extends React.Component {
onPress={() => {
if (item.locked) {
eSendEvent(eOpenVaultDialog, {unlock: true, i: item});
+ return;
+ }
+ if (DDS.isTab) {
+ eSendEvent(eOnLoadNote, item);
+ } else if (isTrash) {
+ simpleDialogEvent(TEMPLATE_TRASH(item.type));
} else {
- DDS.isTab
- ? eSendEvent(eOnLoadNote, item)
- : isTrash
- ? simpleDialogEvent(TEMPLATE_TRASH(item.type))
- : NavigationService.navigate('Editor', {
- note: item,
- });
+ eSendEvent(eOnLoadNote, item);
+ openEditorAnimation();
}
}}
style={{
diff --git a/apps/mobile/src/components/NotebookItem/index.js b/apps/mobile/src/components/NotebookItem/index.js
index 39ad7c277..f1a3fa6b5 100644
--- a/apps/mobile/src/components/NotebookItem/index.js
+++ b/apps/mobile/src/components/NotebookItem/index.js
@@ -193,22 +193,21 @@ export const NotebookItem = ({
)}
- {isTopic && item.totalNotes > 0 ? (
-
- {item && item.totalNotes && item.totalNotes > 1
- ? item.totalNotes + ' notes'
- : item.totalNotes === 1
- ? item.totalNotes + ' note'
- : null}
-
- ) : null}
+
+
+ {item && item.totalNotes && item.totalNotes > 1
+ ? item.totalNotes + ' notes'
+ : item.totalNotes === 1
+ ? item.totalNotes + ' note'
+ : '0 notes'}
+
{hideMore ||
(item.title === 'General' && item.type === 'topic') ? null : (
@@ -243,7 +242,7 @@ export const NotebookItem = ({
onPress={async () => {
let noteIds = [];
selectedItemsList.forEach(item => noteIds.push(item.id));
- console.log(noteIds);
+
db.notes.move(
{
topic: item.title,
diff --git a/apps/mobile/src/components/NotesList/index.js b/apps/mobile/src/components/NotesList/index.js
index 60065356f..5a025e29d 100644
--- a/apps/mobile/src/components/NotesList/index.js
+++ b/apps/mobile/src/components/NotesList/index.js
@@ -18,6 +18,7 @@ import {NotesPlaceHolder} from '../ListPlaceholders';
import NoteItem from '../NoteItem';
import SelectionWrapper from '../SelectionWrapper';
import {db, DDS} from '../../../App';
+import {inputRef} from '../SearchInput';
export const NotesList = ({isGrouped = false}) => {
const [state, dispatch] = useTracked();
@@ -155,12 +156,12 @@ export const NotesList = ({isGrouped = false}) => {
style={{
marginTop:
Platform.OS == 'ios'
- ? notes[0]
+ ? notes[0] && !selectionMode
? DDS.isTab
? 115
: 135
: 135 - 60
- : notes[0]
+ : notes[0] && !selectionMode
? 155
: 155 - 60,
flexDirection: 'row',
@@ -178,6 +179,9 @@ export const NotesList = ({isGrouped = false}) => {
{
+ inputRef.current?.setNativeProps({
+ text: '',
+ });
dispatch({
type: ACTIONS.SEARCH_RESULTS,
results: [],
@@ -194,7 +198,7 @@ export const NotesList = ({isGrouped = false}) => {
);
const _listKeyExtractor = (item, index) => item.id.toString();
- console.log(notes);
+
return isGrouped && searchResults.length === 0 ? (
(sectionListRef = ref)}
@@ -269,7 +273,7 @@ const PinnedItems = () => {
return (
<>
item.id.toString()}
renderItem={({item, index}) =>
item.type === 'note' ? (
@@ -288,6 +292,7 @@ const PinnedItems = () => {
borderBottomWidth: 0,
marginHorizontal: 0,
}}
+ onLongPress={() => {}}
pinned={true}
item={item}
index={index}
diff --git a/apps/mobile/src/components/SearchInput/index.js b/apps/mobile/src/components/SearchInput/index.js
index 40a5544dd..b1a49b3f8 100644
--- a/apps/mobile/src/components/SearchInput/index.js
+++ b/apps/mobile/src/components/SearchInput/index.js
@@ -8,12 +8,14 @@ import {useTracked} from '../../provider';
const {Value, timing, block} = Animated;
+export const inputRef = createRef();
+
export const Search = props => {
const [state, dispatch] = useTracked();
const {colors, searchResults} = state;
const [focus, setFocus] = useState(false);
- const inputRef = createRef();
+
const _marginAnim = new Value(0);
const _opacity = new Value(1);
const _borderAnim = new Value(1.5);
@@ -98,7 +100,7 @@ export const Search = props => {
text: '',
});
}}
- name={searchResults.length > 0 ? 'x' : 'magnify'}
+ name={searchResults.length > 0 ? 'close' : 'magnify'}
color={
focus
? props.headerColor
diff --git a/apps/mobile/src/components/SelectionHeader/index.js b/apps/mobile/src/components/SelectionHeader/index.js
index 122553a4b..f6b89dc05 100644
--- a/apps/mobile/src/components/SelectionHeader/index.js
+++ b/apps/mobile/src/components/SelectionHeader/index.js
@@ -14,8 +14,9 @@ import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {w, ToastEvent} from '../../utils/utils';
import {eSendEvent} from '../../services/eventManager';
-import {eOpenMoveNoteDialog} from '../../services/events';
+import {eOpenMoveNoteDialog, eOpenSimpleDialog} from '../../services/events';
import {db} from '../../../App';
+import {TEMPLATE_DELETE} from '../DialogManager';
export const AnimatedSafeAreaView = Animatable.createAnimatableComponent(
SafeAreaView,
@@ -105,6 +106,7 @@ export const SelectionHeader = ({navigation}) => {
{
dispatch({type: ACTIONS.SELECTION_MODE, enabled: false});
+ dispatch({type: ACTIONS.CLEAR_SELECTION});
eSendEvent(eOpenMoveNoteDialog);
}}>
{
{currentScreen === 'trash' || currentScreen === 'notebooks' ? null : (
{
+ let favCount = 0;
+ let unFavCount = 0;
if (selectedItemsList.length > 0) {
selectedItemsList.forEach(async item => {
+ if (item.favorite) {
+ favCount += 1;
+ } else {
+ unFavCount += 1;
+ }
await db.notes.note(item.id).favorite();
+ dispatch({type: ACTIONS.NOTES});
+ dispatch({type: ACTIONS.FAVORITES});
});
+
dispatch({type: ACTIONS.SELECTION_MODE, enabled: false});
- dispatch({type: ACTIONS.NOTES});
+
dispatch({type: ACTIONS.CLEAR_SELECTION});
- ToastEvent.show('Notes added to favorites', 'success');
+
+ ToastEvent.show(
+ favCount +
+ ' notes added to favorites &' +
+ unFavCount +
+ 'removed',
+ 'success',
+ );
}
}}>
{
{currentScreen === 'trash' ? null : (
{
+ eSendEvent(eOpenSimpleDialog, TEMPLATE_DELETE('item'));
+ return;
if (selectedItemsList.length > 0) {
let noteIds = [];
selectedItemsList.forEach(item => {
diff --git a/apps/mobile/src/components/Toast/index.js b/apps/mobile/src/components/Toast/index.js
index 5bc743650..61befb6d5 100644
--- a/apps/mobile/src/components/Toast/index.js
+++ b/apps/mobile/src/components/Toast/index.js
@@ -65,16 +65,17 @@ export const Toast = () => {
return (
{
}}>
{
borderRadius: 5,
paddingHorizontal: ph,
paddingVertical: pv,
+ opacity: toast ? 1 : 0,
justifyContent: 'center',
elevation: 25,
flexDirection: 'row',
diff --git a/apps/mobile/src/components/VaultDialog/index.js b/apps/mobile/src/components/VaultDialog/index.js
index 3fd97cc75..6385364c9 100644
--- a/apps/mobile/src/components/VaultDialog/index.js
+++ b/apps/mobile/src/components/VaultDialog/index.js
@@ -8,6 +8,7 @@ import {getElevation} from '../../utils/utils';
import NavigationService from '../../services/NavigationService';
import {updateEvent} from '../DialogManager';
+import Share from 'react-native-share';
export class VaultDialog extends Component {
constructor(props) {
@@ -24,24 +25,19 @@ export class VaultDialog extends Component {
});
};
close = (share = false, item = null) => {
- this.setState(
- {
- visible: false,
- },
+ if (share && item) {
+ let m = `${item.title}\n \n ${item.content.text}`;
+ Share.open({
+ title: 'Share note to',
+ failOnCancel: false,
+ message: m,
+ });
+ updateEvent({type: item.type});
+ }
- () => {
- if (share && note) {
- let m = `${item.title}\n \n ${item.content.text}`;
-
- Share.open({
- title: 'Share note to',
- failOnCancel: false,
- message: m,
- });
- }
- updateEvent({type: this.props.note.type});
- },
- );
+ this.setState({
+ visible: false,
+ });
};
onPress = async () => {
diff --git a/apps/mobile/src/provider/defaultState.js b/apps/mobile/src/provider/defaultState.js
index c1fda7da0..2e01c94ba 100644
--- a/apps/mobile/src/provider/defaultState.js
+++ b/apps/mobile/src/provider/defaultState.js
@@ -8,7 +8,10 @@ export const defaultState = {
notebooks: [],
trash: [],
favorites: [],
- pinned: [],
+ pinned: {
+ notes: [],
+ notebooks: [],
+ },
tags: [],
colorNotes: [],
user: {},
diff --git a/apps/mobile/src/provider/reducer.js b/apps/mobile/src/provider/reducer.js
index 8d4367152..6e8035048 100644
--- a/apps/mobile/src/provider/reducer.js
+++ b/apps/mobile/src/provider/reducer.js
@@ -1,5 +1,5 @@
import {db} from '../../App';
-import {SideMenuEvent} from '../utils/utils';
+import {SideMenuEvent, history} from '../utils/utils';
import {ACTIONS} from './actions';
export const reducer = (state, action) => {
@@ -50,10 +50,15 @@ export const reducer = (state, action) => {
};
}
case ACTIONS.PINNED: {
- let pinned = db.notes.pinned;
+ let notes = db.notes.pinned;
+ let notebooks = db.notebooks.pinned;
+
return {
...state,
- pinned: pinned,
+ pinned: {
+ notes,
+ notebooks,
+ },
};
}
case ACTIONS.CURRENT_SCREEN: {
@@ -99,13 +104,16 @@ export const reducer = (state, action) => {
} else {
selectedItems.push(action.item);
}
+ history.selectedItemsList = selectedItems;
return {
...state,
selectedItemsList: selectedItems,
+ selectionMode: selectedItems.length > 0 ? true : false,
};
}
case ACTIONS.CLEAR_SELECTION: {
+ history.selectedItemsList = [];
return {
...state,
selectedItemsList: [],
diff --git a/apps/mobile/src/services/validation.js b/apps/mobile/src/services/validation.js
index de3e5f9dc..95bf33840 100644
--- a/apps/mobile/src/services/validation.js
+++ b/apps/mobile/src/services/validation.js
@@ -1,26 +1,18 @@
-import {ToastEvent} from '../utils/utils';
-
let regex = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
export function validateEmail(email) {
if (email && email.length > 0) {
- ToastEvent.show('Please enter a valid email address');
return regex.test(email);
} else {
- ToastEvent.show('Please enter email or passoword to login');
return false;
}
}
export function validatePass(password) {
if (password && password.length <= 0) {
- ToastEvent.show('No password provided');
-
return false;
}
if (password && password.length < 8 && password.length > 0) {
- ToastEvent.show('Password too short');
-
return false;
} else if (password && password.length > 8 && password.length > 0) {
return true;
@@ -30,10 +22,8 @@ export function validatePass(password) {
export function validateUsername(username) {
let regex = /^[a-z0-9_-]{3,16}$/gim;
if (username && username.length > 0) {
- //ToastEvent.show('Please enter a valid email address');
return regex.test(username);
} else {
- //ToastEvent.show('Please enter email or passoword to login');
return false;
}
}
diff --git a/apps/mobile/src/utils/animations.js b/apps/mobile/src/utils/animations.js
index 0b2159f40..2b3ad2671 100644
--- a/apps/mobile/src/utils/animations.js
+++ b/apps/mobile/src/utils/animations.js
@@ -1,3 +1,28 @@
+import Animated, {Easing} from 'react-native-reanimated';
+import {Dimensions} from 'react-native';
+
+const {color, Value, timing} = Animated;
+
+export const EditorPosition = new Value(Dimensions.get('window').width * 1.5);
+
+export function openEditorAnimation() {
+ let openConfigH = {
+ duration: 300,
+ toValue: 0,
+ easing: Easing.inOut(Easing.ease),
+ };
+ timing(EditorPosition, openConfigH).start();
+}
+
+export function exitEditorAnimation() {
+ let openConfigH = {
+ duration: 300,
+ toValue: Dimensions.get('window').width * 1.5,
+ easing: Easing.inOut(Easing.ease),
+ };
+ timing(EditorPosition, openConfigH).start();
+}
+
export const slideRight = {
0: {
transform: [{translateX: -4}],
diff --git a/apps/mobile/src/utils/storage.js b/apps/mobile/src/utils/storage.js
index 31e4399b4..d98f34c21 100644
--- a/apps/mobile/src/utils/storage.js
+++ b/apps/mobile/src/utils/storage.js
@@ -1,5 +1,6 @@
import {NativeModules} from 'react-native';
import FastStorage from 'react-native-fast-storage';
+
var Aes = NativeModules.Aes;
async function read(key) {
@@ -25,12 +26,16 @@ function encrypt(password, data) {
let key;
return Aes.pbkdf2('password', 'salt', 5000, 256).then(aes => {
key = aes;
- console.log(aes);
return Aes.randomKey(16).then(iv => {
- return Aes.encrypt(data, key, iv).then(cipher => ({
- cipher,
- iv,
- }));
+ return Aes.encrypt(data, key, iv).then(cipher => {
+ return Aes.hmac256(cipher, key).then(hash => {
+ return {
+ hash,
+ cipher,
+ iv,
+ };
+ });
+ });
});
});
}
@@ -40,8 +45,13 @@ function decrypt(password, data) {
return Aes.pbkdf2(password, 'salt', 5000, 256).then(aes => {
key = aes;
- return Aes.decrypt(data.cipher, key, data.iv).then(e => {
- return e;
+ return Aes.hmac256(data.cipher, key).then(hash => {
+ if (hash !== data.hash) {
+ throw new Error('Wrong password');
+ }
+ return Aes.decrypt(data.cipher, key, data.iv).then(e => {
+ return e;
+ });
});
});
}
diff --git a/apps/mobile/src/utils/utils.js b/apps/mobile/src/utils/utils.js
index b6b39f0ff..d10b6e84e 100755
--- a/apps/mobile/src/utils/utils.js
+++ b/apps/mobile/src/utils/utils.js
@@ -18,6 +18,15 @@ export const getElevation = elevation => {
};
};
+export const editing = {
+ currentlyEditing: false,
+ isFullscreen: false,
+};
+
+export const history = {
+ selectedItemsList: [],
+};
+
export function timeSince(date) {
var seconds = Math.floor((new Date() - date) / 1000);
@@ -49,7 +58,7 @@ export const w = Dimensions.get('window').width;
export const h = Dimensions.get('window').height;
export const ToastEvent = {
- show: (message, type, duration = 1000, func = null, actionText = '') => {
+ show: (message, type, duration = 3000, func = null, actionText = '') => {
eSendEvent(eShowToast, {
message,
type,
@@ -58,7 +67,7 @@ export const ToastEvent = {
actionText,
});
},
- hide: (message, type, duration = 1000, func = null, actionText = '') => {
+ hide: (message, type, duration = 3000, func = null, actionText = '') => {
eSendEvent(eHideToast, {
message,
type,
diff --git a/apps/mobile/src/views/Editor/index.js b/apps/mobile/src/views/Editor/index.js
index 71af92bd3..fec9173f2 100755
--- a/apps/mobile/src/views/Editor/index.js
+++ b/apps/mobile/src/views/Editor/index.js
@@ -1,6 +1,5 @@
-import React, {useEffect, useState} from 'react';
+import React, {createRef, useEffect, useState} from 'react';
import {
- ActivityIndicator,
BackHandler,
KeyboardAvoidingView,
Linking,
@@ -9,16 +8,15 @@ import {
Text,
TouchableOpacity,
View,
+ SafeAreaView,
} from 'react-native';
-import * as Animatable from 'react-native-animatable';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import WebView from 'react-native-webview';
import {db, DDS} from '../../../App';
-import {SIZE, WEIGHT, normalize, opacity} from '../../common/common';
+import {normalize, SIZE, WEIGHT} from '../../common/common';
import {
ActionSheetEvent,
simpleDialogEvent,
- TEMPLATE_EXIT,
TEMPLATE_EXIT_FULLSCREEN,
TEMPLATE_INFO,
} from '../../components/DialogManager';
@@ -34,29 +32,39 @@ import {
eOnLoadNote,
eOpenFullscreenEditor,
} from '../../services/events';
-import {SideMenuEvent, timeConverter, ToastEvent} from '../../utils/utils';
-import {AnimatedSafeAreaView} from '../Home';
-import NavigationService from '../../services/NavigationService';
+import {exitEditorAnimation} from '../../utils/animations';
+import {
+ editing,
+ SideMenuEvent,
+ timeConverter,
+ ToastEvent,
+} from '../../utils/utils';
-let EditorWebView;
+const EditorWebView = createRef();
let note = {};
let id = null;
-let dateEdited = null;
var content = null;
var title = null;
let timer = null;
let saveCounter = 0;
let tapCount = 0;
+
const Editor = ({navigation, noMenu}) => {
// Global State
const [state, dispatch] = useTracked();
const {colors} = state;
- const [loading, setLoading] = useState(true);
const [fullscreen, setFullscreen] = useState(false);
-
+ const [dateEdited, setDateEdited] = useState(0);
// FUNCTIONS
- const post = value => EditorWebView.postMessage(value);
+ const post = value => EditorWebView.current?.postMessage(value);
+
+ useEffect(() => {
+ let c = {...colors};
+ c.factor = normalize(1);
+ post(JSON.stringify(c));
+ }, [colors.bg]);
+
useEffect(() => {
eSubscribeEvent(eOnLoadNote, loadNote);
@@ -65,56 +73,44 @@ const Editor = ({navigation, noMenu}) => {
};
}, []);
- useEffect(() => {
- setLoading(true);
- setTimeout(() => {
- setLoading(false);
- }, 3000);
- }, [colors.bg]);
-
- const loadNote = item => {
+ const loadNote = async item => {
if (note && note.id) {
- saveNote(true).then(() => {
- dispatch({type: ACTIONS.NOTES});
- if (item && item.type === 'new') {
- clearEditor();
- } else {
- note = item;
- if (DDS.isTab) {
- dispatch({
- type: ACTIONS.CURRENT_EDITING_NOTE,
- id: item.id,
- });
- }
-
- updateEditor();
- }
- });
+ dispatch({type: ACTIONS.NOTES});
+ if (item && item.type === 'new') {
+ await clearEditor();
+ } else {
+ note = item;
+ dispatch({
+ type: ACTIONS.CURRENT_EDITING_NOTE,
+ id: item.id,
+ });
+ updateEditor();
+ }
} else {
dispatch({type: ACTIONS.NOTES});
if (item && item.type === 'new') {
- clearEditor();
+ await clearEditor();
} else {
note = item;
- if (DDS.isTab) {
- dispatch({
- type: ACTIONS.CURRENT_EDITING_NOTE,
- id: item.id,
- });
- }
+ dispatch({
+ type: ACTIONS.CURRENT_EDITING_NOTE,
+ id: item.id,
+ });
updateEditor();
}
}
};
- const clearEditor = () => {
- id = null;
+ const clearEditor = async () => {
+ await saveNote();
title = null;
content = null;
- note = {};
+ note = null;
+ id = null;
+ tapCount = 0;
saveCounter = 0;
- EditorWebView.reload();
-
+ post('clear');
+ post(JSON.stringify({type: 'text', value: ''}));
post('focusTitle');
};
@@ -131,7 +127,6 @@ const Editor = ({navigation, noMenu}) => {
const _onMessage = evt => {
if (evt.nativeEvent.data === 'loaded') {
- setLoading(false);
} else if (
evt.nativeEvent.data !== '' &&
evt.nativeEvent.data !== 'loaded'
@@ -165,8 +160,6 @@ const Editor = ({navigation, noMenu}) => {
};
}
- console.log(content.delta, 'i am called');
-
let rId = await db.notes.add({
title,
content: {
@@ -189,8 +182,7 @@ const Editor = ({navigation, noMenu}) => {
}
}, 500);
}
-
- if (DDS.isTab) {
+ if (id) {
dispatch({
type: ACTIONS.CURRENT_EDITING_NOTE,
id: id,
@@ -248,17 +240,10 @@ const Editor = ({navigation, noMenu}) => {
);
}
- if (navigation && navigation.state.params && navigation.state.params.note) {
- note = navigation.state.params.note;
-
- updateEditor();
- } else if (note && note.id) {
+ if (note && note.id) {
updateEditor();
} else {
post('focusTitle');
- wait(500).then(() => {
- setLoading(false);
- });
}
let c = {...colors};
c.factor = normalize(1);
@@ -274,17 +259,14 @@ const Editor = ({navigation, noMenu}) => {
});
const updateEditor = async () => {
- console.log('before', content, title, id);
title = note.title;
id = note.id;
- dateEdited = note.dateEdited;
+ setDateEdited(note.dateEdited);
content = note.content;
if (!note.locked) {
content.delta = await db.notes.note(id).delta();
}
- console.log('after', content, title, id);
-
saveCounter = 0;
if (title !== null || title === '') {
@@ -297,18 +279,11 @@ const Editor = ({navigation, noMenu}) => {
} else {
post('focusTitle');
post('clear');
- wait(500).then(() => {
- setLoading(false);
- });
}
if (note.content.text === '' && note.content.delta === null) {
post('clear');
- wait(500).then(() => {
- setLoading(false);
- });
} else if (note.content.delta) {
let delta;
- console.log(note.content.delta, 'HERE');
if (typeof note.content.delta !== 'string') {
delta = note.content.delta;
} else {
@@ -318,9 +293,6 @@ const Editor = ({navigation, noMenu}) => {
post(JSON.stringify(delta));
} else {
post(JSON.stringify({type: 'text', value: note.content.text}));
- wait(2000).then(() => {
- setLoading(false);
- });
}
};
@@ -334,8 +306,92 @@ const Editor = ({navigation, noMenu}) => {
link.click();
}`;
- const _renderEditor = () => {
- return (
+ const closeFullscreen = () => {
+ setFullscreen(false);
+ };
+
+ // EFFECTS
+
+ useEffect(() => {
+ eSubscribeEvent(eCloseFullscreenEditor, closeFullscreen);
+
+ return () => {
+ eUnSubscribeEvent(eCloseFullscreenEditor, closeFullscreen);
+ };
+ });
+
+ const _onHardwareBackPress = async () => {
+ if (tapCount > 0) {
+ exitEditorAnimation();
+ await clearEditor();
+ ToastEvent.show('Note Saved!', 'success');
+ return true;
+ } else {
+ tapCount = 1;
+ setTimeout(() => {
+ tapCount = 0;
+ }, 3000);
+ ToastEvent.show('Press back again to exit editor', 'success');
+ return true;
+ }
+ };
+
+ useEffect(() => {
+ editing.currentlyEditing = true;
+
+ let handleBack;
+ if (!noMenu && DDS.isTab) {
+ handleBack = BackHandler.addEventListener('hardwareBackPress', () => {
+ simpleDialogEvent(TEMPLATE_EXIT_FULLSCREEN());
+ editing.isFullscreen = false;
+ return true;
+ });
+ } else if (!DDS.isTab) {
+ handleBack = BackHandler.addEventListener(
+ 'hardwareBackPress',
+ _onHardwareBackPress,
+ );
+ } else {
+ if (handleBack) {
+ handleBack.remove();
+ handleBack = null;
+ }
+ }
+
+ return () => {
+ editing.currentlyEditing = false;
+ if (handleBack) {
+ handleBack.remove();
+ handleBack = null;
+ }
+ title = null;
+ content = null;
+ id = null;
+ timer = null;
+ note = {};
+ };
+ }, [noMenu]);
+
+ useEffect(() => {
+ noMenu ? null : SideMenuEvent.disable();
+
+ return () => {
+ if (noMenu) return;
+ DDS.isTab ? SideMenuEvent.open() : null;
+ SideMenuEvent.enable();
+ };
+ });
+
+ return (
+
{
{noMenu ? null : (
{
+ onPress={async () => {
if (DDS.isTab) {
simpleDialogEvent(TEMPLATE_EXIT_FULLSCREEN());
} else {
- tapCount = 0;
- title = null;
- content = null;
- note = null;
- id = null;
-
- NavigationService.goBack();
+ exitEditorAnimation();
+ await clearEditor();
+ ToastEvent.show('Note Saved!', 'success');
}
}}
style={{
@@ -401,6 +453,7 @@ const Editor = ({navigation, noMenu}) => {
onPress={() => {
eSendEvent(eOpenFullscreenEditor);
setFullscreen(true);
+ editing.isFullscreen = true;
post(
JSON.stringify({
type: 'nomenu',
@@ -468,7 +521,7 @@ const Editor = ({navigation, noMenu}) => {
(EditorWebView = ref)}
+ ref={EditorWebView}
onError={error => console.log(error)}
onLoad={onWebViewLoad}
javaScriptEnabled={true}
@@ -510,133 +563,7 @@ const Editor = ({navigation, noMenu}) => {
onMessage={_onMessage}
/>
- );
- };
-
- const closeFullscreen = () => {
- setFullscreen(false);
- };
-
- // EFFECTS
-
- useEffect(() => {
- eSubscribeEvent(eCloseFullscreenEditor, closeFullscreen);
-
- return () => {
- eUnSubscribeEvent(eCloseFullscreenEditor, closeFullscreen);
- };
- });
-
- useEffect(() => {
- let handleBack;
- if (!noMenu && DDS.isTab) {
- handleBack = BackHandler.addEventListener('hardwareBackPress', () => {
- simpleDialogEvent(TEMPLATE_EXIT_FULLSCREEN());
- return true;
- });
- } else if (!DDS.isTab) {
- handleBack = BackHandler.addEventListener('hardwareBackPress', () => {
- console.log('tapCOunt', tapCount);
- if (tapCount > 0) {
- tapCount = 0;
- title = null;
- content = null;
- note = null;
- id = null;
- return false;
- } else {
- tapCount = 1;
- setTimeout(() => {
- tapCount = 0;
- }, 3000);
- ToastEvent.show('Press back again to exit editor', 'success');
- return true;
- }
- });
- } else {
- console.log(' I RUN EVERYTIME');
- if (handleBack) {
- handleBack.remove();
- handleBack = null;
- }
- }
-
- return () => {
- if (handleBack) {
- handleBack.remove();
- handleBack = null;
- }
- title = null;
- content = null;
- id = null;
- timer = null;
- note = {};
- };
- }, [noMenu]);
-
- useEffect(() => {
- noMenu ? null : SideMenuEvent.disable();
-
- return () => {
- if (noMenu) return;
- DDS.isTab ? SideMenuEvent.open() : null;
- SideMenuEvent.enable();
- };
- });
-
- useEffect(() => {
- EditorWebView.reload();
- }, [colors]);
-
- return (
-
-
-
-
-
- Write with confidence.
-
-
-
-
- {_renderEditor()}
-
-
+
);
};
diff --git a/apps/mobile/src/views/Favorites/index.js b/apps/mobile/src/views/Favorites/index.js
index 746d4def2..ae2b3a925 100644
--- a/apps/mobile/src/views/Favorites/index.js
+++ b/apps/mobile/src/views/Favorites/index.js
@@ -10,19 +10,24 @@ import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent} from '../../services/eventManager';
import {eScrollEvent} from '../../services/events';
-import {ToastEvent} from '../../utils/utils';
+import {ToastEvent, w} from '../../utils/utils';
+import {useIsFocused} from 'react-navigation-hooks';
export const Favorites = ({navigation}) => {
const [state, dispatch] = useTracked();
const {colors, selectionMode, favorites} = state;
const [refreshing, setRefreshing] = useState(false);
+ const isFocused = useIsFocused();
+
useEffect(() => {
- dispatch({
- type: ACTIONS.CURRENT_SCREEN,
- screen: 'favorites',
- });
- dispatch({type: ACTIONS.FAVORITES});
- }, []);
+ if (isFocused) {
+ dispatch({
+ type: ACTIONS.CURRENT_SCREEN,
+ screen: 'favorites',
+ });
+ dispatch({type: ACTIONS.FAVORITES});
+ }
+ }, [isFocused]);
const onScroll = event => {
let y = event.nativeEvent.contentOffset.y;
diff --git a/apps/mobile/src/views/Folders/index.js b/apps/mobile/src/views/Folders/index.js
index f51edd1b0..f8251b734 100644
--- a/apps/mobile/src/views/Folders/index.js
+++ b/apps/mobile/src/views/Folders/index.js
@@ -34,45 +34,37 @@ export const Folders = ({navigation}) => {
const [refreshing, setRefreshing] = useState(false);
let isFocused = useIsFocused();
- ///
-
const handleBackPress = () => {
alert('here');
return true;
};
+ useEffect(() => {
+ if (isFocused) {
+ dispatch({type: ACTIONS.PINNED});
+ dispatch({type: ACTIONS.NOTEBOOKS});
+ dispatch({
+ type: ACTIONS.CURRENT_SCREEN,
+ screen: 'notebooks',
+ });
+ }
+ }, [isFocused]);
+
useEffect(() => {
eSendEvent(eScrollEvent, 0);
- dispatch({type: ACTIONS.NOTEBOOKS});
-
- if (isFocused) {
- if (isFocused) {
- dispatch({
- type: ACTIONS.CURRENT_SCREEN,
- screen: 'notebooks',
- });
- }
- }
-
let backhandler;
- if (isFocused) {
- backhandler = BackHandler.addEventListener(
- 'hardwareBackPress',
- handleBackPress,
- );
- } else {
- if (backhandler) {
- backhandler.remove();
- backhandler = null;
- }
- }
+
+ backhandler = BackHandler.addEventListener(
+ 'hardwareBackPress',
+ handleBackPress,
+ );
return () => {
if (!backhandler) return;
backhandler.remove();
backhandler = null;
};
- }, [isFocused]);
+ }, []);
const params = navigation.state.params;
@@ -134,38 +126,36 @@ export const Folders = ({navigation}) => {
? 155
: 155 - 60,
}}>
- {pinned && pinned.length > 0 ? (
+ {pinned && pinned.notebooks && pinned.notebooks.length > 0 ? (
<>
item.id.toString()}
renderItem={({item, index}) =>
item.type === 'notebook' ? (
-
- {
- dispatch({
- type: ACTIONS.SELECTION_MODE,
- enabled: !selectionMode,
- });
- dispatch({
- type: ACTIONS.SELECTED_ITEMS,
- item: item,
- });
- }}
- noteToMove={params.note}
- item={item}
- pinned={true}
- index={index}
- colors={colors}
- />
-
+ {}}
+ noteToMove={params.note}
+ item={item}
+ pinned={true}
+ index={index}
+ colors={colors}
+ />
) : null
}
/>
@@ -174,31 +164,29 @@ export const Folders = ({navigation}) => {
}
ListEmptyComponent={
- pinned && pinned.length > 0 ? null : (
-
-
-
-
+
+
+
+
-
- Notebooks you add will appear here
-
-
- )
+
+ Notebooks you add will appear here
+
+
}
contentContainerStyle={{
width: '100%',
diff --git a/apps/mobile/src/views/Notebook/index.js b/apps/mobile/src/views/Notebook/index.js
index 127794dec..b107322e8 100644
--- a/apps/mobile/src/views/Notebook/index.js
+++ b/apps/mobile/src/views/Notebook/index.js
@@ -35,7 +35,6 @@ export const Notebook = ({navigation}) => {
allTopics = db.notebooks.notebook(navigation.state.params.notebook.id).data
.topics;
- console.log(allTopics);
notebook = db.notebooks.notebook(navigation.state.params.notebook.id);
@@ -67,13 +66,15 @@ export const Notebook = ({navigation}) => {
type: ACTIONS.CURRENT_SCREEN,
screen: 'notebook',
});
+ onLoad();
}
-
+ }, [isFocused]);
+ useEffect(() => {
eSubscribeEvent(eMoveNoteDialogNavigateBack, handleBackPress);
return () => {
eUnSubscribeEvent(eMoveNoteDialogNavigateBack, handleBackPress);
};
- }, [isFocused]);
+ }, []);
const onScroll = event => {
let y = event.nativeEvent.contentOffset.y;
diff --git a/apps/mobile/src/views/Notes/index.js b/apps/mobile/src/views/Notes/index.js
index c00787de7..06cea7a3a 100644
--- a/apps/mobile/src/views/Notes/index.js
+++ b/apps/mobile/src/views/Notes/index.js
@@ -18,6 +18,7 @@ import {ToastEvent} from '../../utils/utils';
import {eSendEvent} from '../../services/eventManager';
import {eScrollEvent} from '../../services/events';
import {NotesPlaceHolder} from '../../components/ListPlaceholders';
+import {useIsFocused} from 'react-navigation-hooks';
export const Notes = ({navigation}) => {
const [state, dispatch] = useTracked();
@@ -25,6 +26,7 @@ export const Notes = ({navigation}) => {
const allNotes = state.notes;
const [notes, setNotes] = useState([]);
const [refreshing, setRefreshing] = useState(false);
+ const isFocused = useIsFocused();
let params = navigation.state ? navigation.state.params : null;
useEffect(() => {
@@ -34,6 +36,15 @@ export const Notes = ({navigation}) => {
};
}
}, []);
+ useEffect(() => {
+ if (isFocused) {
+ init();
+ dispatch({
+ type: ACTIONS.CURRENT_SCREEN,
+ screen: params.type,
+ });
+ }
+ }, [isFocused, allNotes, colorNotes]);
const init = () => {
eSendEvent(eScrollEvent, 0);
@@ -49,18 +60,12 @@ export const Notes = ({navigation}) => {
.notebook(params.notebookId)
.topics.topic(params.title).all;
- console.log(allNotes, 'here getting topics');
-
if (allNotes && allNotes.length > 0) {
setNotes(allNotes);
}
}
};
- useEffect(() => {
- init();
- }, [allNotes, colorNotes]);
-
const _renderItem = ({item, index}) => (
{
const [state, dispatch] = useTracked();
const {colors, tags, selectionMode} = state;
const [refreshing, setRefreshing] = useState(false);
+ const isFocused = useIsFocused();
useEffect(() => {
- dispatch({type: ACTIONS.TAGS});
- dispatch({
- type: ACTIONS.CURRENT_SCREEN,
- screen: 'tags',
- });
- }, []);
+ if (isFocused) {
+ dispatch({type: ACTIONS.TAGS});
+ dispatch({
+ type: ACTIONS.CURRENT_SCREEN,
+ screen: 'tags',
+ });
+ }
+ }, [isFocused]);
return (
{
const [state, dispatch] = useTracked();
const {colors, selectionMode, trash} = state;
const [refreshing, setRefreshing] = useState(false);
- useEffect(() => {
- dispatch({
- type: ACTIONS.TRASH,
- });
+ const isFocused = useIsFocused();
- dispatch({
- type: ACTIONS.CURRENT_SCREEN,
- screen: 'trash',
- });
- }, []);
+ useEffect(() => {
+ if (isFocused) {
+ dispatch({
+ type: ACTIONS.TRASH,
+ });
+
+ dispatch({
+ type: ACTIONS.CURRENT_SCREEN,
+ screen: 'trash',
+ });
+ }
+ }, [isFocused]);
const _renderItem = ({item, index}) => (