mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 15:09:33 +01:00
Merge branch 'master' of https://github.com/thecodrr/notes-mobile
This commit is contained in:
@@ -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 = () => {
|
||||
/>
|
||||
</SideMenu>
|
||||
)}
|
||||
|
||||
<Animated.View
|
||||
ref={ref => (editorRef = ref)}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
zIndex: 10,
|
||||
backgroundColor: colors.bg,
|
||||
elevation: 10,
|
||||
transform: [
|
||||
{
|
||||
translateX: EditorPosition,
|
||||
},
|
||||
],
|
||||
}}>
|
||||
<Editor noMenu={false} />
|
||||
</Animated.View>
|
||||
|
||||
<Toast />
|
||||
|
||||
<DialogManager colors={colors} />
|
||||
</Animatable.View>
|
||||
</>
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
|
||||
<Text
|
||||
@@ -680,11 +697,21 @@ export const ActionSheetComponent = ({
|
||||
borderColor: focused ? colors.accent : colors.nav,
|
||||
paddingVertical: 5,
|
||||
}}>
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
tagsInputRef.current?.focus();
|
||||
}}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}></TouchableOpacity>
|
||||
{note && note.tags ? note.tags.map(_renderTag) : null}
|
||||
<TextInput
|
||||
style={{
|
||||
backgroundColor: 'transparent',
|
||||
minWidth: 100,
|
||||
zIndex: 10,
|
||||
fontFamily: WEIGHT.regular,
|
||||
color: colors.pri,
|
||||
paddingHorizontal: 5,
|
||||
@@ -692,7 +719,7 @@ export const ActionSheetComponent = ({
|
||||
margin: 1,
|
||||
}}
|
||||
blurOnSubmit={false}
|
||||
ref={ref => (tagsInputRef = ref)}
|
||||
ref={tagsInputRef}
|
||||
placeholderTextColor={colors.icon}
|
||||
onFocus={() => {
|
||||
setFocused(true);
|
||||
|
||||
@@ -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}>
|
||||
<KeyboardAvoidingView
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : null}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, {createRef} from 'react';
|
||||
import {Modal, Text, TouchableOpacity, View} from 'react-native';
|
||||
import {TextInput} from 'react-native-gesture-handler';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
@@ -18,6 +18,7 @@ export class AddTopicDialog extends React.Component {
|
||||
};
|
||||
|
||||
this.title;
|
||||
this.titleRef = createRef();
|
||||
}
|
||||
|
||||
addNewTopic = async () => {
|
||||
@@ -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 {
|
||||
</View>
|
||||
|
||||
<TextInput
|
||||
ref={this.titleRef}
|
||||
style={{
|
||||
padding: pv,
|
||||
borderWidth: 1.5,
|
||||
|
||||
@@ -11,16 +11,17 @@ import {db, DDS} from '../../../App';
|
||||
import {opacity, ph, pv, SIZE, WEIGHT} from '../../common/common';
|
||||
import {ACTIONS} from '../../provider/actions';
|
||||
import NavigationService from '../../services/NavigationService';
|
||||
import {getElevation, ToastEvent} from '../../utils/utils';
|
||||
import {getElevation, ToastEvent, editing, history} from '../../utils/utils';
|
||||
import {dialogActions, updateEvent} from '../DialogManager';
|
||||
import {eSendEvent} from '../../services/eventManager';
|
||||
import {eCloseFullscreenEditor} from '../../services/events';
|
||||
import {eCloseFullscreenEditor, eOnLoadNote} from '../../services/events';
|
||||
|
||||
export class Dialog extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
visible: false,
|
||||
selecteItemsLength: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,29 +30,41 @@ export class Dialog extends Component {
|
||||
|
||||
switch (template.action) {
|
||||
case dialogActions.ACTION_DELETE: {
|
||||
if (item.type === 'note') {
|
||||
await db.notes.delete(item.id);
|
||||
|
||||
ToastEvent.show('Note moved to trash', 'error', 3000);
|
||||
updateEvent({type: item.type});
|
||||
} else if (item.type === 'topic') {
|
||||
console.log(item);
|
||||
//TODO
|
||||
|
||||
await db.notebooks
|
||||
.notebook(item.notebookId)
|
||||
.topics.delete(item.title);
|
||||
updateEvent({type: 'notebook'});
|
||||
ToastEvent.show('Topic deleted', 'error', 3000);
|
||||
} else if (item.type === 'notebook') {
|
||||
await db.notebooks.delete(item.id);
|
||||
updateEvent({type: item.type});
|
||||
ToastEvent.show('Notebook moved to trash', 'error', 3000);
|
||||
if (item.id && history.selectedItemsList.length === 0) {
|
||||
history.selectedItemsList = [];
|
||||
history.selectedItemsList.push(item);
|
||||
}
|
||||
history.selectedItemsList.forEach(async i => {
|
||||
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}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
|
||||
@@ -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 = ({
|
||||
)}
|
||||
|
||||
<ScrollView
|
||||
contentContainerStyle={{minHeight: '80%'}}
|
||||
contentContainerStyle={{minHeight: '50%'}}
|
||||
style={{
|
||||
paddingHorizontal: noTextMode ? 0 : 12,
|
||||
}}
|
||||
@@ -201,7 +202,12 @@ export const Menu = ({
|
||||
activeOpacity={opacity / 2}
|
||||
onPress={() => {
|
||||
item.close === false ? null : close();
|
||||
|
||||
if (item.close) {
|
||||
inputRef.current?.setNativeProps({
|
||||
text: '',
|
||||
});
|
||||
dispatch({type: ACTIONS.SEARCH_RESULTS, results: []});
|
||||
}
|
||||
item.func();
|
||||
}}
|
||||
style={{
|
||||
|
||||
@@ -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={{
|
||||
|
||||
@@ -193,22 +193,21 @@ export const NotebookItem = ({
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
{isTopic && item.totalNotes > 0 ? (
|
||||
<Text
|
||||
style={{
|
||||
color: colors.icon,
|
||||
fontSize: SIZE.xxs,
|
||||
textAlignVertical: 'center',
|
||||
fontFamily: WEIGHT.regular,
|
||||
marginTop: 5,
|
||||
}}>
|
||||
{item && item.totalNotes && item.totalNotes > 1
|
||||
? item.totalNotes + ' notes'
|
||||
: item.totalNotes === 1
|
||||
? item.totalNotes + ' note'
|
||||
: null}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
<Text
|
||||
style={{
|
||||
color: colors.icon,
|
||||
fontSize: SIZE.xxs,
|
||||
textAlignVertical: 'center',
|
||||
fontFamily: WEIGHT.regular,
|
||||
marginTop: 5,
|
||||
}}>
|
||||
{item && item.totalNotes && item.totalNotes > 1
|
||||
? item.totalNotes + ' notes'
|
||||
: item.totalNotes === 1
|
||||
? item.totalNotes + ' note'
|
||||
: '0 notes'}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
{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,
|
||||
|
||||
@@ -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}) => {
|
||||
</Text>
|
||||
<Text
|
||||
onPress={() => {
|
||||
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 ? (
|
||||
<SectionList
|
||||
ref={ref => (sectionListRef = ref)}
|
||||
@@ -269,7 +273,7 @@ const PinnedItems = () => {
|
||||
return (
|
||||
<>
|
||||
<FlatList
|
||||
data={pinned}
|
||||
data={pinned.notes}
|
||||
keyExtractor={(item, index) => 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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}) => {
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
dispatch({type: ACTIONS.SELECTION_MODE, enabled: false});
|
||||
dispatch({type: ACTIONS.CLEAR_SELECTION});
|
||||
eSendEvent(eOpenMoveNoteDialog);
|
||||
}}>
|
||||
<Icon
|
||||
@@ -120,14 +122,31 @@ export const SelectionHeader = ({navigation}) => {
|
||||
{currentScreen === 'trash' || currentScreen === 'notebooks' ? null : (
|
||||
<TouchableOpacity
|
||||
onPress={async () => {
|
||||
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',
|
||||
);
|
||||
}
|
||||
}}>
|
||||
<Icon
|
||||
@@ -144,6 +163,8 @@ export const SelectionHeader = ({navigation}) => {
|
||||
{currentScreen === 'trash' ? null : (
|
||||
<TouchableOpacity
|
||||
onPress={async () => {
|
||||
eSendEvent(eOpenSimpleDialog, TEMPLATE_DELETE('item'));
|
||||
return;
|
||||
if (selectedItemsList.length > 0) {
|
||||
let noteIds = [];
|
||||
selectedItemsList.forEach(item => {
|
||||
|
||||
@@ -65,16 +65,17 @@ export const Toast = () => {
|
||||
return (
|
||||
<Animatable.View
|
||||
transition={['translateY', 'opacity']}
|
||||
duration={500}
|
||||
duration={10}
|
||||
delay={toast ? 300 : 0}
|
||||
useNativeDriver={true}
|
||||
style={{
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
height: 60,
|
||||
opacity: toast ? 1 : 0,
|
||||
bottom: 100,
|
||||
position: 'absolute',
|
||||
zIndex: 999,
|
||||
elevation: 15,
|
||||
transform: [
|
||||
{
|
||||
translateY: toast ? 0 : 300,
|
||||
@@ -83,6 +84,8 @@ export const Toast = () => {
|
||||
}}>
|
||||
<AnimatedTouchableOpacity
|
||||
activeOpacity={opacity + 0.1}
|
||||
transition={['opacity']}
|
||||
duration={300}
|
||||
style={{
|
||||
...toastStyle,
|
||||
maxWidth: DDS.isTab ? normalize(350) : w - 24,
|
||||
@@ -91,6 +94,7 @@ export const Toast = () => {
|
||||
borderRadius: 5,
|
||||
paddingHorizontal: ph,
|
||||
paddingVertical: pv,
|
||||
opacity: toast ? 1 : 0,
|
||||
justifyContent: 'center',
|
||||
elevation: 25,
|
||||
flexDirection: 'row',
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -8,7 +8,10 @@ export const defaultState = {
|
||||
notebooks: [],
|
||||
trash: [],
|
||||
favorites: [],
|
||||
pinned: [],
|
||||
pinned: {
|
||||
notes: [],
|
||||
notebooks: [],
|
||||
},
|
||||
tags: [],
|
||||
colorNotes: [],
|
||||
user: {},
|
||||
|
||||
@@ -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: [],
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}],
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 (
|
||||
<SafeAreaView
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: DDS.isTab ? 'transparent' : colors.bg,
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
}}>
|
||||
<KeyboardAvoidingView
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : null}
|
||||
style={{
|
||||
@@ -349,17 +405,13 @@ const Editor = ({navigation, noMenu}) => {
|
||||
|
||||
{noMenu ? null : (
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
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}) => {
|
||||
</Text>
|
||||
</View>
|
||||
<WebView
|
||||
ref={ref => (EditorWebView = ref)}
|
||||
ref={EditorWebView}
|
||||
onError={error => console.log(error)}
|
||||
onLoad={onWebViewLoad}
|
||||
javaScriptEnabled={true}
|
||||
@@ -510,133 +563,7 @@ const Editor = ({navigation, noMenu}) => {
|
||||
onMessage={_onMessage}
|
||||
/>
|
||||
</KeyboardAvoidingView>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<AnimatedSafeAreaView
|
||||
transition={['backgroundColor', 'width']}
|
||||
duration={300}
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: DDS.isTab ? 'transparent' : colors.bg,
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
}}>
|
||||
<Animatable.View
|
||||
transition="opacity"
|
||||
useNativeDriver={true}
|
||||
duration={150}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
zIndex: 1,
|
||||
backgroundColor: colors.bg,
|
||||
opacity: loading ? 1 : 0,
|
||||
position: 'absolute',
|
||||
}}>
|
||||
<ActivityIndicator color={colors.accent} size={SIZE.xxxl} />
|
||||
|
||||
<Text
|
||||
style={{
|
||||
color: colors.accent,
|
||||
fontFamily: WEIGHT.regular,
|
||||
fontSize: SIZE.md,
|
||||
marginTop: 10,
|
||||
}}>
|
||||
Write with confidence.
|
||||
</Text>
|
||||
</Animatable.View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
zIndex: 2,
|
||||
opacity: loading ? 0 : 1,
|
||||
}}>
|
||||
{_renderEditor()}
|
||||
</View>
|
||||
</AnimatedSafeAreaView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ? (
|
||||
<>
|
||||
<FlatList
|
||||
data={pinned}
|
||||
data={pinned.notebooks}
|
||||
keyExtractor={(item, index) => item.id.toString()}
|
||||
renderItem={({item, index}) =>
|
||||
item.type === 'notebook' ? (
|
||||
<SelectionWrapper item={item}>
|
||||
<NotebookItem
|
||||
hideMore={params.hideMore}
|
||||
customStyle={{
|
||||
width: selectionMode ? w - 74 : '100%',
|
||||
marginHorizontal: 0,
|
||||
}}
|
||||
isMove={params.isMove}
|
||||
onLongPress={() => {
|
||||
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}
|
||||
/>
|
||||
</SelectionWrapper>
|
||||
<NotebookItem
|
||||
hideMore={params.hideMore}
|
||||
customStyle={{
|
||||
backgroundColor: Platform.ios
|
||||
? hexToRGBA(colors.accent + '19')
|
||||
: hexToRGBA(colors.shade),
|
||||
width: '100%',
|
||||
paddingHorizontal: 12,
|
||||
paddingTop: 20,
|
||||
paddingRight: 18,
|
||||
marginBottom: 10,
|
||||
marginTop: 20,
|
||||
borderBottomWidth: 0,
|
||||
marginHorizontal: 0,
|
||||
}}
|
||||
isMove={params.isMove}
|
||||
onLongPress={() => {}}
|
||||
noteToMove={params.note}
|
||||
item={item}
|
||||
pinned={true}
|
||||
index={index}
|
||||
colors={colors}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
@@ -174,31 +164,29 @@ export const Folders = ({navigation}) => {
|
||||
</View>
|
||||
}
|
||||
ListEmptyComponent={
|
||||
pinned && pinned.length > 0 ? null : (
|
||||
<View
|
||||
style={{
|
||||
height: '80%',
|
||||
width: DDS.isTab ? '70%' : '100%',
|
||||
alignItems: 'center',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
opacity: 0.8,
|
||||
}}>
|
||||
<NotebookPlaceHolder animation={slideRight} colors={colors} />
|
||||
<NotebookPlaceHolder animation={slideLeft} colors={colors} />
|
||||
<NotebookPlaceHolder animation={slideRight} colors={colors} />
|
||||
<View
|
||||
style={{
|
||||
height: '80%',
|
||||
width: DDS.isTab ? '70%' : '100%',
|
||||
alignItems: 'center',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
opacity: 0.8,
|
||||
}}>
|
||||
<NotebookPlaceHolder animation={slideRight} colors={colors} />
|
||||
<NotebookPlaceHolder animation={slideLeft} colors={colors} />
|
||||
<NotebookPlaceHolder animation={slideRight} colors={colors} />
|
||||
|
||||
<Text
|
||||
style={{
|
||||
color: colors.icon,
|
||||
fontSize: SIZE.sm,
|
||||
fontFamily: WEIGHT.regular,
|
||||
marginTop: 30,
|
||||
}}>
|
||||
Notebooks you add will appear here
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
<Text
|
||||
style={{
|
||||
color: colors.icon,
|
||||
fontSize: SIZE.sm,
|
||||
fontFamily: WEIGHT.regular,
|
||||
marginTop: 30,
|
||||
}}>
|
||||
Notebooks you add will appear here
|
||||
</Text>
|
||||
</View>
|
||||
}
|
||||
contentContainerStyle={{
|
||||
width: '100%',
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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}) => (
|
||||
<SelectionWrapper
|
||||
index={index}
|
||||
|
||||
@@ -15,6 +15,7 @@ import {useTracked} from '../../provider';
|
||||
import {ACTIONS} from '../../provider/actions';
|
||||
import NavigationService from '../../services/NavigationService';
|
||||
import {ToastEvent} from '../../utils/utils';
|
||||
import {useIsFocused} from 'react-navigation-hooks';
|
||||
const w = Dimensions.get('window').width;
|
||||
const h = Dimensions.get('window').height;
|
||||
|
||||
@@ -22,13 +23,16 @@ export const Tags = ({navigation}) => {
|
||||
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 (
|
||||
<Container
|
||||
|
||||
@@ -13,21 +13,26 @@ import {useTracked} from '../../provider';
|
||||
import {ACTIONS} from '../../provider/actions';
|
||||
import {w, ToastEvent} from '../../utils/utils';
|
||||
import SelectionWrapper from '../../components/SelectionWrapper';
|
||||
import {useIsFocused} from 'react-navigation-hooks';
|
||||
|
||||
export const Trash = ({navigation}) => {
|
||||
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}) => (
|
||||
<SelectionWrapper colors={colors} item={item}>
|
||||
|
||||
Reference in New Issue
Block a user