import React, { createRef } from 'react'; import { Keyboard, KeyboardAvoidingView, Modal, Platform, SafeAreaView, StyleSheet, TouchableOpacity, View } from 'react-native'; import { FlatList, TextInput } from 'react-native-gesture-handler'; import { notesnook } from '../../../e2e/test.ids'; import { Actions } from '../../provider/Actions'; import { DDS } from '../../services/DeviceDetection'; import { ToastEvent } from '../../services/EventManager'; import { db } from '../../utils/DB'; import { ph, pv, SIZE } from '../../utils/SizeUtils'; import { ActionIcon } from '../ActionIcon'; import DialogButtons from '../Dialog/dialog-buttons'; import DialogHeader from '../Dialog/dialog-header'; import { updateEvent } from '../DialogManager/recievers'; import Input from '../Input'; import { Toast } from '../Toast'; import Paragraph from '../Typography/Paragraph'; let refs = []; export class AddNotebookDialog extends React.Component { constructor(props) { super(props); this.state = { visible: false, topics: [], description: null, titleFocused: false, descFocused: false, count: 0, topicInputFocused: false, editTopic: false, }; this.title = null; this.description = null; this.listRef; this.prevItem = null; this.prevIndex = null; this.currentSelectedInput = null; this.id = null; this.backPressCount = 0; this.currentInputValue = null; this.titleRef; this.descriptionRef; this.topicsToDelete = []; this.hiddenInput = createRef(); this.topicInputRef = createRef(); this.addingTopic = false; } open = () => { refs = []; let {toEdit} = this.props; if (toEdit && toEdit.type === 'notebook') { let topicsList = []; toEdit.topics.forEach((item, index) => { if (index === 0) return; topicsList.push(item.title); }); this.id = toEdit.id; this.title = toEdit.title; this.description = toEdit.description; this.setState({ topics: [...topicsList], visible: true, }); } else { this.setState({ visible: true, }); } }; close = () => { refs = []; this.prevIndex = null; this.prevItem = null; this.currentSelectedInput = null; this.title = null; this.description = null; this.currentInputValue = null; this.id = null; this.setState({ visible: false, topics: [], descFocused: false, titleFocused: false, editTopic: false, }); }; onDelete = (index) => { let {topics} = this.state; let prevTopics = topics; refs = []; prevTopics.splice(index, 1); let edit = this.props.toEdit; if (edit && edit.id) { let topicToDelete = edit.topics[index + 1]; if (topicToDelete) { this.topicsToDelete.push(topicToDelete.id); } } let nextTopics = [...prevTopics]; if (this.prevIndex === index) { this.prevIndex = null; this.prevItem = null; this.currentInputValue = null; this.topicInputRef.current?.setNativeProps({ text: null, }); } this.setState({ topics: nextTopics, }); }; addNewNotebook = async () => { let {topics} = this.state; let edit = this.props.toEdit; if (!this.title || this.title?.trim().length === 0) return ToastEvent.show('Notebook title is required', 'error', 'local'); let id = edit && edit.id ? edit.id : null; let toEdit; if (id) { toEdit = db.notebooks.notebook(edit.id).data; } let prevTopics = [...topics]; if (this.currentInputValue && this.currentInputValue.trim().length !== 0) { if (this.prevItem != null) { prevTopics[this.prevIndex] = this.currentInputValue; } else { prevTopics.push(this.currentInputValue); this.currentInputValue = null; } } if (id) { if (this.topicsToDelete?.length > 0) { await db.notebooks .notebook(toEdit.id) .topics.delete(...this.topicsToDelete); toEdit = db.notebooks.notebook(toEdit.id).data; } await db.notebooks.add({ title: this.title, description: this.description, id: id, }); let nextTopics = toEdit.topics.map((topic, index) => { if (index === 0) return topic; let copy = {...topic}; copy.title = prevTopics[index - 1]; return copy; }); prevTopics.forEach((title, index) => { if (!nextTopics[index + 1]) { nextTopics.push(title); } }); await db.notebooks.notebook(id).topics.add(...nextTopics); } else { await db.notebooks.add({ title: this.title, description: this.description, topics: prevTopics, id: id, }); } this.close(); updateEvent({type: Actions.NOTEBOOKS}); updateEvent({type: Actions.PINNED}); }; onSubmit = (forward = true) => { this.hiddenInput.current?.focus(); let {topics} = this.state; if (!this.currentInputValue || this.currentInputValue?.trim().length === 0) return; let prevTopics = [...topics]; if (this.prevItem === null) { prevTopics.push(this.currentInputValue); this.setState({ topics: prevTopics, }); setTimeout(() => { this.listRef.scrollToEnd({animated: true}); }, 30); this.currentInputValue = null; } else { prevTopics[this.prevIndex] = this.currentInputValue; this.setState({ topics: prevTopics, }); this.currentInputValue = null; console.log('edit topic is', this.state.editTopic); if (this.state.editTopic) { this.topicInputRef.current?.blur(); Keyboard.dismiss(); this.setState({ editTopic: false, }); } this.prevItem = null; this.prevIndex = null; this.currentInputValue = null; if (forward) { setTimeout(() => { this.listRef.scrollToEnd({animated: true}); }, 30); } } this.topicInputRef.current?.focus(); }; render() { const {colors, toEdit} = this.props; const { titleFocused, descFocused, topics, visible, topicInputFocused, } = this.state; if (!visible) return null; return ( { this.topicsToDelete = []; this.titleRef?.focus(); }} onRequestClose={this.close}> (this.titleRef = ref)} testID={notesnook.ids.dialogs.notebook.inputs.title} onChangeText={(value) => { this.title = value; }} placeholder="Enter a Title" onSubmit={() => { this.descriptionRef.focus(); }} defaultValue={toEdit ? toEdit.title : null} /> (this.descriptionRef = ref)} testID={notesnook.ids.dialogs.notebook.inputs.description} onChangeText={(value) => { this.description = value; }} placeholder="Describe your notebook." onSubmit={() => { this.topicInputRef.current?.focus(); }} defaultValue={toEdit ? toEdit.description : null} /> { this.currentInputValue = value; if (this.prevItem !== null) { refs[this.prevIndex].setNativeProps({ text: value, style: { borderBottomColor: colors.accent, }, }); } }} onSubmit={() => { this.onSubmit(); }} blurOnSubmit={false} button={{ icon: this.state.editTopic ? 'check' : 'plus', onPress: this.onSubmit, color: topicInputFocused ? colors.accent : colors.icon, }} placeholder="Add a topic" /> (this.listRef = ref)} keyExtractor={(item, index) => item + index.toString()} renderItem={({item, index}) => ( { this.prevIndex = index; this.prevItem = item; this.topicInputRef.current?.setNativeProps({ text: item, }); this.topicInputRef.current?.focus(); this.currentInputValue = item; this.setState({ editTopic: true, }); }} onDelete={this.onDelete} index={index} colors={colors} /> )} /> ); } } const TopicItem = ({item, index, colors, onPress, onDelete}) => { const topicRef = (ref) => (refs[index] = ref); return ( { onPress(item, index); }} /> {index + 1 + '.'} { onPress(item, index); }} name="pencil" size={SIZE.lg - 5} color={colors.icon} /> { onDelete(index); }} name="minus" size={SIZE.lg} color={colors.icon} /> ); }; const styles = StyleSheet.create({ wrapper: { width: '100%', height: '100%', backgroundColor: 'rgba(0,0,0,0.3)', justifyContent: 'center', alignItems: 'center', }, container: { width: DDS.isTab ? 500 : '100%', height: DDS.isTab ? 600 : '100%', maxHeight: DDS.isTab ? 600 : '100%', borderRadius: DDS.isTab ? 5 : 0, paddingHorizontal: 12, paddingVertical: pv, }, overlay: { width: '100%', height: '100%', position: 'absolute', }, headingContainer: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }, headingText: { marginLeft: 5, fontSize: SIZE.xl, }, input: { paddingRight: 12, paddingHorizontal: 0, borderRadius: 0, minHeight: 45, fontSize: SIZE.md, padding: pv - 2, borderBottomWidth: 1, marginTop: 10, marginBottom: 5, }, addBtn: { width: '12%', minHeight: 45, justifyContent: 'center', alignItems: 'center', position: 'absolute', right: 0, }, buttonContainer: { justifyContent: 'space-between', alignItems: 'center', flexDirection: 'row', width: '100%', marginTop: 20, }, topicContainer: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginTop: 10, }, topicInput: { padding: pv - 5, fontSize: SIZE.sm, //fontFamily: "sans-serif", paddingHorizontal: ph, paddingRight: 40, paddingVertical: 10, width: '100%', maxWidth: '100%', }, topicBtn: { borderRadius: 5, width: 40, height: 40, justifyContent: 'center', alignItems: 'center', position: 'absolute', right: 0, }, });