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

430 lines
15 KiB
JavaScript
Raw Normal View History

import React, {createRef, useEffect, useRef, useState} from 'react';
import {Keyboard} from 'react-native';
import {ScrollView} from 'react-native';
import {FlatList, TextInput, TouchableOpacity, View} from 'react-native';
2020-09-14 16:45:41 +05:00
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
2020-12-14 15:02:18 +05:00
import {notesnook} from '../../../e2e/test.ids';
2020-09-14 17:10:02 +05:00
import {useTracked} from '../../provider';
2020-10-13 17:02:14 +05:00
import {Actions} from '../../provider/Actions';
2020-11-23 12:32:33 +05:00
import {DDS} from '../../services/DeviceDetection';
2020-11-20 01:23:05 +05:00
import {
eSendEvent,
2020-11-20 01:23:05 +05:00
eSubscribeEvent,
eUnSubscribeEvent,
ToastEvent,
} from '../../services/EventManager';
import {dHeight} from '../../utils';
2020-11-23 12:32:33 +05:00
import {db} from '../../utils/DB';
import {
eOnNewTopicAdded,
eOpenMoveNoteDialog,
refreshNotesPage,
} from '../../utils/Events';
2020-11-23 12:32:33 +05:00
import {pv, SIZE, WEIGHT} from '../../utils/SizeUtils';
import {ActionIcon} from '../ActionIcon';
import ActionSheet from '../ActionSheet';
2020-11-23 15:57:31 +05:00
import DialogHeader from '../Dialog/dialog-header';
2020-09-14 17:10:02 +05:00
import {PressableButton} from '../PressableButton';
import {Toast} from '../Toast';
2020-11-20 01:23:05 +05:00
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
let newNotebookTitle = null;
let newTopicTitle = null;
const notebookInput = createRef();
const topicInput = createRef();
2020-09-14 16:45:41 +05:00
const MoveNoteDialog = () => {
const [state, dispatch] = useTracked();
const {colors} = state;
2020-09-14 17:10:02 +05:00
const [visible, setVisible] = useState(false);
const [note, setNote] = useState(null);
const actionSheetRef = useRef();
function open(note) {
setNote(note);
2020-09-14 16:45:41 +05:00
setVisible(true);
actionSheetRef.current?._setModalVisible(true);
2020-09-14 16:45:41 +05:00
}
const close = () => {
actionSheetRef.current?._setModalVisible(false);
};
useEffect(() => {
eSubscribeEvent(eOpenMoveNoteDialog, open);
return () => {
eUnSubscribeEvent(eOpenMoveNoteDialog, open);
};
}, []);
const _onClose = () => {
2020-09-14 16:45:41 +05:00
setVisible(false);
newTopicTitle = null;
newNotebookTitle = null;
setNote(null);
eSendEvent(refreshNotesPage);
eSendEvent(eOnNewTopicAdded);
dispatch({type: Actions.CLEAR_SELECTION});
dispatch({type: Actions.NOTEBOOKS});
dispatch({type: Actions.NOTES});
2020-09-14 16:45:41 +05:00
};
2020-01-18 18:13:34 +05:00
const style = React.useMemo(() => {
return {
width: DDS.isLargeTablet() ? 500 : '100%',
height: DDS.isLargeTablet() ? 500 : null,
maxHeight: DDS.isLargeTablet() ? 500 : '90%',
borderTopRightRadius: DDS.isLargeTablet() ? 5 : 10,
borderTopLeftRadius: DDS.isLargeTablet() ? 5 : 10,
backgroundColor: colors.bg,
padding: DDS.isLargeTablet() ? 8 : 0,
zIndex: 10,
paddingVertical: 12,
2020-01-18 18:13:34 +05:00
};
}, [colors.bg]);
return !visible ? null : (
<ActionSheet
ref={actionSheetRef}
animationType="slide"
containerStyle={style}
gestureEnabled
initialOffsetFromBottom={1}
onClose={_onClose}>
<IntComponent close={close} note={note} />
</ActionSheet>
);
};
export default MoveNoteDialog;
const IntComponent = ({close, note}) => {
const [state, dispatch] = useTracked();
const {colors, selectedItemsList} = state;
const [expanded, setExpanded] = useState('');
const [notebookInputFocused, setNotebookInputFocused] = useState(false);
const [topicInputFocused, setTopicInputFocused] = useState(false);
2020-01-18 18:13:34 +05:00
2020-09-14 16:45:41 +05:00
const addNewNotebook = async () => {
if (!newNotebookTitle || newNotebookTitle.trim().length === 0)
return ToastEvent.show('Title is required', 'error', 'local');
2020-01-18 18:13:34 +05:00
2020-09-14 16:45:41 +05:00
await db.notebooks.add({
title: newNotebookTitle,
description: null,
2020-09-14 16:45:41 +05:00
topics: [],
id: null,
2020-01-18 18:13:34 +05:00
});
notebookInput.current?.clear();
notebookInput.current?.blur();
2020-10-13 17:02:14 +05:00
dispatch({type: Actions.NOTEBOOKS});
2020-09-14 16:45:41 +05:00
};
2020-01-18 18:13:34 +05:00
2020-09-14 16:45:41 +05:00
const addNewTopic = async () => {
if (!newTopicTitle || newTopicTitle.trim().length === 0) {
2020-09-14 16:45:41 +05:00
return ToastEvent.show('Title is required', 'error', 'local');
}
await db.notebooks.notebook(expanded).topics.add(newTopicTitle);
2020-10-13 17:02:14 +05:00
dispatch({type: Actions.NOTEBOOKS});
topicInput.current?.clear();
topicInput.current?.blur();
newTopicTitle = null;
2020-09-14 16:45:41 +05:00
};
return (
<>
<View>
<TouchableOpacity
2020-01-18 18:13:34 +05:00
style={{
2020-01-23 23:19:06 +05:00
width: '100%',
height: '100%',
position: 'absolute',
}}
onPress={() => {
Keyboard.dismiss();
}}
/>
<View
style={{
paddingHorizontal: 12,
flexDirection: 'row',
justifyContent: 'space-between',
2020-09-14 16:45:41 +05:00
}}>
<DialogHeader
title="Add to notebook"
paragraph={`Add your notes in notebooks to find them easily.`}
2020-11-23 15:57:31 +05:00
/>
</View>
2020-11-23 15:57:31 +05:00
<ScrollView nestedScrollEnabled>
<View>
2020-11-23 15:57:31 +05:00
<View
2020-09-14 16:45:41 +05:00
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 10,
width: '100%',
borderBottomWidth: 1,
borderColor: colors.nav,
2020-11-23 15:57:31 +05:00
paddingHorizontal: 12,
}}>
<TextInput
ref={notebookInput}
onChangeText={(value) => {
newNotebookTitle = value;
}}
testID={notesnook.ids.dialogs.addTo.addNotebook}
blurOnSubmit={false}
onFocus={() => {
setNotebookInputFocused(true);
}}
onBlur={() => {
setNotebookInputFocused(false);
}}
onSubmitEditing={addNewNotebook}
style={[
{
color: colors.pri,
width: '90%',
maxWidth: '90%',
paddingHorizontal: 0,
borderRadius: 5,
minHeight: 45,
fontSize: SIZE.md,
fontFamily: WEIGHT.regular,
padding: pv - 2,
},
]}
placeholder="Create a new notebook"
placeholderTextColor={colors.icon}
2020-11-23 15:57:31 +05:00
/>
<TouchableOpacity
onPress={addNewNotebook}
testID={notesnook.ids.dialogs.addTo.addNotebook}
style={[
{
borderRadius: 5,
minHeight: 45,
justifyContent: 'center',
alignItems: 'center',
},
]}>
<Icon
name="plus"
size={SIZE.lg}
color={notebookInputFocused ? colors.accent : colors.icon}
/>
</TouchableOpacity>
2020-11-23 15:57:31 +05:00
</View>
</View>
2020-09-14 16:45:41 +05:00
{state.notebooks.map((item) => (
<View>
<PressableButton
onPress={() => {
setExpanded(item.id === expanded ? null : item.id);
setTopicInputFocused(false);
setNotebookInputFocused(false);
}}
type="gray"
customStyle={{
height: 50,
width: '100%',
borderRadius: 0,
alignItems: 'flex-start',
marginBottom: 5,
borderBottomWidth: 1,
borderBottomColor:
expanded === item.id ? colors.accent : colors.nav,
}}>
2020-09-14 16:45:41 +05:00
<View
style={{
width: '100%',
height: 50,
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
2020-09-14 16:45:41 +05:00
paddingHorizontal: 12,
}}>
<View>
<Heading
color={expanded === item.id ? colors.accent : null}
size={SIZE.md}>
{item.title}
</Heading>
<Paragraph size={SIZE.xs} color={colors.icon}>
Notebook{' '}
{item.totalNotes +
' notes' +
' & ' +
item.topics.length +
' topics'}
</Paragraph>
2020-09-14 16:45:41 +05:00
</View>
<Icon
name={expanded === item.id ? 'chevron-up' : 'chevron-down'}
color={colors.pri}
size={SIZE.lg}
/>
2020-11-23 15:57:31 +05:00
</View>
</PressableButton>
2020-09-14 16:45:41 +05:00
{expanded === item.id ? (
<FlatList
data={item.topics}
keyboardShouldPersistTaps="always"
keyboardDismissMode="none"
ListHeaderComponent={
<View>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
alignSelf: 'flex-end',
marginBottom: 5,
marginTop: 5,
borderBottomWidth: 1,
paddingHorizontal: 12,
borderColor: colors.nav,
}}>
<TextInput
ref={topicInput}
onChangeText={(value) => {
newTopicTitle = value;
}}
testID={notesnook.ids.dialogs.addTo.addTopic}
blurOnSubmit={false}
onFocus={() => {
setTopicInputFocused(true);
}}
onBlur={() => {
setTopicInputFocused(false);
}}
onSubmitEditing={addNewTopic}
style={[
{
color: colors.pri,
2020-11-23 15:57:31 +05:00
width: '90%',
maxWidth: '90%',
paddingHorizontal: 0,
borderRadius: 5,
height: 40,
fontSize: SIZE.sm,
fontFamily: WEIGHT.regular,
padding: pv - 2,
},
]}
placeholder="Add a topic"
placeholderTextColor={colors.icon}
/>
<TouchableOpacity
onPress={addNewTopic}
testID={notesnook.ids.dialogs.addTo.btnTopic}
style={[
{
borderRadius: 5,
height: 40,
justifyContent: 'center',
alignItems: 'center',
},
]}>
<Icon
name="plus"
size={SIZE.lg}
color={
topicInputFocused ? colors.accent : colors.icon
}
/>
</TouchableOpacity>
</View>
</View>
}
renderItem={({item, index}) => (
<PressableButton
onPress={async () => {
if (
note &&
note.notebooks &&
note.notebooks.findIndex((o) =>
o.topics.findIndex((e) => e === item.id),
)
) {
await db.notebooks
.notebook(item.notebookId)
.topics.topic(item.id)
.delete(note.id);
if (note && note.id) {
console.log('updating note');
setNote({...db.notes.note(note.id).data});
}
2020-11-23 15:57:31 +05:00
dispatch({type: Actions.NOTEBOOKS});
return;
}
let noteIds = [];
selectedItemsList.forEach((i) => noteIds.push(i.id));
await db.notes.move(
{
topic: item.id,
id: item.notebookId,
},
...noteIds,
);
console.log(item.id, item.notebookId);
if (note && note.id) {
console.log('updating note');
setNote({...db.notes.note(note.id).data});
}
dispatch({type: Actions.NOTEBOOKS});
}}
type="gray"
customStyle={{
height: 50,
borderTopWidth: index === 0 ? 0 : 1,
borderTopColor: colors.nav,
width: '100%',
borderRadius: 0,
alignItems: 'center',
flexDirection: 'row',
paddingHorizontal: 12,
justifyContent: 'space-between',
}}>
<View>
<Paragraph color={colors.heading}>
{item.title}
{'\n'}
<Paragraph color={colors.icon} size={SIZE.xs}>
{item.totalNotes + ' notes'}
</Paragraph>
</Paragraph>
</View>
{note?.notebooks?.findIndex(
(o) => o.topics.indexOf(item.id) > -1,
) > -1 ? (
<Paragraph size={SIZE.sm} color={colors.errorText}>
Remove Note
</Paragraph>
) : null}
</PressableButton>
)}
/>
) : null}
2020-12-01 11:19:29 +05:00
</View>
))}
<View
style={{
height: 100,
}}
/>
</ScrollView>
</View>
<Toast context="local" />
</>
2020-09-14 16:45:41 +05:00
);
};