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

413 lines
13 KiB
JavaScript
Raw Normal View History

2022-01-22 12:57:05 +05:00
import React, { createRef, useEffect, useState } from 'react';
import { Keyboard, TouchableOpacity, View } from 'react-native';
2022-01-22 12:57:05 +05:00
import { FlatList } from 'react-native-gesture-handler';
import { notesnook } from '../../../e2e/test.ids';
import { useTracked } from '../../provider';
import { useNotebookStore, useSelectionStore } from '../../provider/stores';
import { eSubscribeEvent, eUnSubscribeEvent, ToastEvent } from '../../services/EventManager';
2021-02-15 11:09:01 +05:00
import Navigation from '../../services/Navigation';
import { getTotalNotes } from '../../utils';
2022-01-22 12:57:05 +05:00
import { db } from '../../utils/database';
2022-02-28 13:48:59 +05:00
import { eOpenMoveNoteDialog } from '../../utils/events';
import layoutmanager from '../../utils/layout-manager';
2022-02-28 13:48:59 +05:00
import { SIZE } from '../../utils/size';
import { IconButton } from '../ui/icon-button';
import { Button } from '../ui/button';
import { Dialog } from '../dialog';
import DialogHeader from '../dialog/dialog-header';
import { presentDialog } from '../dialog/functions';
import Input from '../ui/input';
import { PressableButton } from '../ui/pressable';
import SheetWrapper from '../ui/sheet';
import Heading from '../ui/typography/heading';
import Paragraph from '../ui/typography/paragraph';
let newNotebookTitle = null;
const notebookInput = createRef();
2020-12-16 11:02:40 +05:00
const actionSheetRef = createRef();
2020-09-14 16:45:41 +05:00
const MoveNoteDialog = () => {
2020-09-14 17:10:02 +05:00
const [visible, setVisible] = useState(false);
const [note, setNote] = useState(null);
2021-02-15 11:09:01 +05:00
function open(note) {
setNote(note);
2020-09-14 16:45:41 +05:00
setVisible(true);
2020-12-29 11:24:34 +05:00
actionSheetRef.current?.setModalVisible(true);
2020-09-14 16:45:41 +05:00
}
const close = () => {
2020-12-29 11:24:34 +05:00
actionSheetRef.current?.setModalVisible(false);
};
useEffect(() => {
eSubscribeEvent(eOpenMoveNoteDialog, open);
return () => {
eUnSubscribeEvent(eOpenMoveNoteDialog, open);
};
}, []);
const _onClose = () => {
2020-09-14 16:45:41 +05:00
setVisible(false);
newNotebookTitle = null;
setNote(null);
2021-02-15 11:09:01 +05:00
Navigation.setRoutesToUpdate([
Navigation.routeNames.Notes,
Navigation.routeNames.Favorites,
Navigation.routeNames.NotesPage,
Navigation.routeNames.Notebook,
2021-12-27 18:09:00 +05:00
Navigation.routeNames.Notebooks
2021-02-15 11:09:01 +05:00
]);
2020-09-14 16:45:41 +05:00
};
2020-01-18 18:13:34 +05:00
2021-07-17 20:40:09 +05:00
const update = note => {
2020-12-16 11:02:40 +05:00
setNote(note);
};
return !visible ? null : (
2021-12-25 11:16:33 +05:00
<SheetWrapper fwdRef={actionSheetRef} onClose={_onClose}>
2020-12-19 13:15:34 +05:00
<MoveNoteComponent close={close} note={note} setNote={update} />
2021-12-25 11:16:33 +05:00
</SheetWrapper>
);
};
export default MoveNoteDialog;
2022-01-22 12:57:05 +05:00
const MoveNoteComponent = ({ close, note, setNote }) => {
const [state, dispatch] = useTracked();
2022-01-22 12:57:05 +05:00
const { colors } = state;
2021-06-05 21:10:20 +05:00
const notebooks = useNotebookStore(state => state.notebooks.filter(n => n?.type === 'notebook'));
2021-12-31 15:01:43 +05:00
2021-06-05 21:10:20 +05:00
const selectedItemsList = useSelectionStore(state => state.selectedItemsList);
const setNotebooks = useNotebookStore(state => state.setNotebooks);
const [expanded, setExpanded] = useState('');
const [notebookInputFocused, setNotebookInputFocused] = useState(false);
const [noteExists, setNoteExists] = useState([]);
2020-09-14 16:45:41 +05:00
const addNewNotebook = async () => {
if (!newNotebookTitle || newNotebookTitle.trim().length === 0)
2021-02-20 15:03:02 +05:00
return ToastEvent.show({
heading: 'Notebook title is required',
type: 'error',
2021-12-27 18:09:00 +05:00
context: 'local'
2021-02-20 15:03:02 +05:00
});
2020-01-18 18:13:34 +05:00
2021-12-27 18:09:00 +05:00
let id = await db.notebooks.add({
2020-09-14 16:45:41 +05:00
title: newNotebookTitle,
description: null,
2020-09-14 16:45:41 +05:00
topics: [],
2021-12-27 18:09:00 +05:00
id: null
2020-01-18 18:13:34 +05:00
});
2021-12-31 09:05:44 +05:00
console.log('added notebook id', id);
2021-12-27 18:09:00 +05:00
setExpanded(id);
openAddTopicDialog(db.notebooks.notebook(id).data);
notebookInput.current?.clear();
notebookInput.current?.blur();
2021-06-05 21:10:20 +05:00
setNotebooks();
2021-12-27 18:09:00 +05:00
updateNoteExists();
2020-09-14 16:45:41 +05:00
};
2020-01-18 18:13:34 +05:00
2021-12-31 09:05:44 +05:00
const addNewTopic = async (value, item) => {
2021-12-27 18:09:00 +05:00
if (!value || value.trim().length === 0) {
ToastEvent.show({
2021-02-20 15:03:02 +05:00
heading: 'Topic title is required',
type: 'error',
2021-12-27 18:09:00 +05:00
context: 'local'
2021-02-20 15:03:02 +05:00
});
2021-12-27 18:09:00 +05:00
return false;
}
2021-12-27 18:09:00 +05:00
console.log(item.id);
await db.notebooks.notebook(item.id).topics.add(value);
2021-06-05 21:10:20 +05:00
setNotebooks();
2021-12-27 18:09:00 +05:00
updateNoteExists();
return true;
2020-09-14 16:45:41 +05:00
};
2020-12-19 13:15:34 +05:00
const handlePress = async (item, index) => {
if (note && item.notes.indexOf(note.id) > -1) {
2022-01-22 12:57:05 +05:00
await db.notebooks.notebook(item.notebookId).topics.topic(item.id).delete(note.id);
if (note && note.id) {
2022-01-22 12:57:05 +05:00
setNote({ ...db.notes.note(note.id).data });
2021-12-31 09:05:44 +05:00
requestAnimationFrame(() => {
2021-12-31 15:01:43 +05:00
//layoutmanager.withSpringAnimation(500);
2021-12-31 09:05:44 +05:00
Navigation.setRoutesToUpdate([
Navigation.routeNames.NotesPage,
Navigation.routeNames.Favorites,
Navigation.routeNames.Notes
]);
});
}
2021-06-05 21:10:20 +05:00
setNotebooks();
2021-12-27 18:09:00 +05:00
updateNoteExists();
2020-12-29 17:19:32 +05:00
return;
}
let noteIds = [];
2021-07-17 20:40:09 +05:00
selectedItemsList.forEach(i => noteIds.push(i.id));
2021-01-06 14:58:01 +05:00
await db.notes.move(
{
topic: item.id,
2021-12-27 18:09:00 +05:00
id: item.notebookId
},
2021-12-27 18:09:00 +05:00
...noteIds
);
if (note && note.id) {
2022-01-22 12:57:05 +05:00
setNote({ ...db.notes.note(note.id).data });
2021-12-31 09:05:44 +05:00
requestAnimationFrame(() => {
2021-12-31 15:01:43 +05:00
//layoutmanager.withSpringAnimation(500);
2021-12-31 09:05:44 +05:00
Navigation.setRoutesToUpdate([
Navigation.routeNames.NotesPage,
Navigation.routeNames.Favorites,
Navigation.routeNames.Notes
]);
});
}
2021-06-05 21:10:20 +05:00
setNotebooks();
2021-12-27 18:09:00 +05:00
updateNoteExists();
};
useEffect(() => {
2021-12-27 18:09:00 +05:00
updateNoteExists();
}, []);
const updateNoteExists = () => {
if (!note?.id) return;
let ids = [];
2021-12-27 18:09:00 +05:00
let notebooks = db.notebooks.all;
for (let i = 0; i < notebooks.length; i++) {
2021-07-17 20:40:09 +05:00
if (notebooks[i].topics) {
for (let t = 0; t < notebooks[i].topics.length; t++) {
if (notebooks[i].topics[t].notes.indexOf(note.id) > -1) {
ids.push(notebooks[i].id);
}
}
}
}
setNoteExists(ids);
2021-12-27 18:09:00 +05:00
};
const openAddTopicDialog = item => {
presentDialog({
context: 'move_note',
input: true,
inputPlaceholder: 'Enter title',
title: 'New topic',
paragraph: 'Add a new topic in ' + item.title,
positiveText: 'Add',
positivePress: value => {
2021-12-31 09:05:44 +05:00
return addNewTopic(value, item);
2021-12-27 18:09:00 +05:00
}
});
};
return (
<>
2021-12-27 18:09:00 +05:00
<Dialog context="move_note" />
<View>
<TouchableOpacity
2020-01-18 18:13:34 +05:00
style={{
2020-01-23 23:19:06 +05:00
width: '100%',
height: '100%',
2021-12-27 18:09:00 +05:00
position: 'absolute'
}}
onPress={() => {
Keyboard.dismiss();
}}
/>
<View
style={{
paddingHorizontal: 12,
flexDirection: 'row',
2021-12-27 18:09:00 +05:00
justifyContent: 'space-between'
2022-01-22 12:57:05 +05:00
}}
>
<DialogHeader
title="Add to notebook"
2021-12-31 09:05:44 +05:00
paragraph={`Add your notes to notebooks to find them easily.`}
2020-11-23 15:57:31 +05:00
/>
</View>
2020-11-23 15:57:31 +05:00
2020-12-29 11:24:34 +05:00
<FlatList
nestedScrollEnabled={true}
2020-12-16 11:02:40 +05:00
onMomentumScrollEnd={() => {
2020-12-29 17:19:32 +05:00
actionSheetRef.current?.handleChildScrollEnd();
2020-12-16 11:02:40 +05:00
}}
2020-12-29 11:24:34 +05:00
keyboardShouldPersistTaps="always"
keyboardDismissMode="none"
2021-02-22 09:59:34 +05:00
data={notebooks}
2020-12-29 11:24:34 +05:00
ListFooterComponent={
<View
style={{
height: 200
2020-12-29 11:24:34 +05:00
}}
/>
}
ListHeaderComponent={
2020-11-23 15:57:31 +05:00
<View
2020-09-14 16:45:41 +05:00
style={{
width: '100%',
2021-12-27 18:09:00 +05:00
marginTop: 10
2022-01-22 12:57:05 +05:00
}}
>
2021-12-27 18:09:00 +05:00
<Input
fwdRef={notebookInput}
2021-07-17 20:40:09 +05:00
onChangeText={value => {
newNotebookTitle = value;
}}
testID={notesnook.ids.dialogs.addTo.addNotebook}
blurOnSubmit={false}
2021-12-27 18:09:00 +05:00
onFocusInput={() => {
setNotebookInputFocused(true);
}}
2021-12-27 18:09:00 +05:00
onBlurInput={() => {
setNotebookInputFocused(false);
}}
2021-12-27 18:09:00 +05:00
button={{
icon: 'check',
color: notebookInputFocused ? colors.accent : colors.icon,
2022-01-22 12:57:05 +05:00
onPress: addNewNotebook
2021-12-27 18:09:00 +05:00
}}
onSubmit={addNewNotebook}
placeholder="Create a new notebook"
2020-11-23 15:57:31 +05:00
/>
</View>
2020-12-29 11:24:34 +05:00
}
2021-12-27 18:09:00 +05:00
style={{
paddingHorizontal: 12
}}
2022-01-22 12:57:05 +05:00
renderItem={({ item, index }) => (
2020-12-29 11:24:34 +05:00
<View
style={{
2021-12-27 18:09:00 +05:00
borderWidth: 1,
borderColor: expanded ? colors.nav : 'transparent',
borderRadius: 6,
overflow: 'hidden',
marginBottom: 10
2022-01-22 12:57:05 +05:00
}}
>
<PressableButton
onPress={() => {
2021-12-27 18:09:00 +05:00
if (!item.topics || item.topics.length === 0) {
setExpanded(item.id);
openAddTopicDialog(item);
return;
}
2021-12-31 09:05:44 +05:00
layoutmanager.withAnimation(200);
setExpanded(item.id === expanded ? null : item.id);
setNotebookInputFocused(false);
}}
2021-12-27 18:09:00 +05:00
type="grayBg"
customStyle={{
height: 50,
width: '100%',
2021-12-27 18:09:00 +05:00
borderRadius: 5,
alignItems: 'flex-start'
2022-01-22 12:57:05 +05:00
}}
>
2020-09-14 16:45:41 +05:00
<View
style={{
width: '100%',
height: 50,
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
2021-12-27 18:09:00 +05:00
paddingHorizontal: 12
2022-01-22 12:57:05 +05:00
}}
>
<View>
<Heading
2022-01-22 12:57:05 +05:00
color={noteExists.indexOf(item.id) > -1 ? colors.accent : null}
size={SIZE.md}
>
{item.title}
</Heading>
2021-07-17 20:40:09 +05:00
{item.topics?.length > 0 ? (
<Paragraph size={SIZE.xs} color={colors.icon}>
{getTotalNotes(item) + ' notes' + ' & '}
{item.topics.length === 1
? item.topics.length + ' topic'
: item.topics.length + ' topics'}
</Paragraph>
) : null}
2020-09-14 16:45:41 +05:00
</View>
2022-02-28 13:48:59 +05:00
<IconButton
2021-12-27 18:09:00 +05:00
name={expanded === item.id ? 'plus' : 'chevron-down'}
color={expanded === item.id ? colors.accent : colors.pri}
size={SIZE.xl}
onPress={() => {
if (expanded !== item.id) {
setExpanded(item.id);
return;
}
2021-12-31 09:05:44 +05:00
layoutmanager.withAnimation(200);
2021-12-27 18:09:00 +05:00
setExpanded(item.id);
openAddTopicDialog(item);
}}
/>
2020-11-23 15:57:31 +05:00
</View>
</PressableButton>
2020-09-14 16:45:41 +05:00
{expanded === item.id ? (
<FlatList
2020-12-29 11:24:34 +05:00
nestedScrollEnabled
data={item.topics}
keyboardShouldPersistTaps="always"
keyboardDismissMode="none"
2020-12-29 11:24:34 +05:00
onMomentumScrollEnd={() => {
2020-12-29 17:19:32 +05:00
actionSheetRef.current?.handleChildScrollEnd();
2020-12-29 11:24:34 +05:00
}}
2020-12-20 18:24:33 +05:00
style={{
2021-12-27 18:09:00 +05:00
width: '100%',
2020-12-29 11:24:34 +05:00
alignSelf: 'flex-end',
2021-12-27 18:09:00 +05:00
maxHeight: 500
2020-12-20 18:24:33 +05:00
}}
2022-01-22 12:57:05 +05:00
renderItem={({ item, index }) => (
<PressableButton
2020-12-19 13:15:34 +05:00
onPress={() => handlePress(item, index)}
type="gray"
customStyle={{
height: 50,
borderTopWidth: index === 0 ? 0 : 1,
2021-12-27 18:09:00 +05:00
borderTopColor: index === 0 ? null : colors.nav,
width: '100%',
borderRadius: 0,
alignItems: 'center',
flexDirection: 'row',
paddingHorizontal: 12,
2021-12-27 18:09:00 +05:00
justifyContent: 'space-between'
2022-01-22 12:57:05 +05:00
}}
>
<View>
2022-01-22 12:57:05 +05:00
<Paragraph color={colors.heading}>{item.title}</Paragraph>
2021-01-14 17:41:27 +05:00
<Paragraph color={colors.icon} size={SIZE.xs}>
{item.notes.length + ' notes'}
2021-02-15 11:09:01 +05:00
</Paragraph>
</View>
{note && item.notes.indexOf(note.id) > -1 ? (
2021-01-14 15:45:07 +05:00
<Button
onPress={() => handlePress(item, index)}
2021-12-27 18:09:00 +05:00
icon="check"
iconColor={colors.accent}
iconSize={SIZE.lg}
height={35}
width={35}
2021-01-14 15:45:07 +05:00
style={{
borderRadius: 100,
2021-12-27 18:09:00 +05:00
paddingHorizontal: 0
2021-01-14 15:45:07 +05:00
}}
/>
) : null}
</PressableButton>
)}
/>
) : null}
2020-12-01 11:19:29 +05:00
</View>
2020-12-29 11:24:34 +05:00
)}
/>
</View>
</>
2020-09-14 16:45:41 +05:00
);
};