diff --git a/ReactNativeClient/lib/components/action-button.js b/ReactNativeClient/lib/components/action-button.js index 2e8b1061cd..9a192fdfb8 100644 --- a/ReactNativeClient/lib/components/action-button.js +++ b/ReactNativeClient/lib/components/action-button.js @@ -1,6 +1,7 @@ const React = require('react'); const { StyleSheet } = require('react-native'); +const Note = require('lib/models/Note'); const Icon = require('react-native-vector-icons/Ionicons').default; const ReactNativeActionButton = require('react-native-action-button').default; const { connect } = require('react-redux'); @@ -33,24 +34,25 @@ class ActionButtonComponent extends React.Component { } } - newTodo_press() { + async newNoteNavigate(folderId, isTodo) { + const newNote = await Note.save({ + parent_id: folderId, + is_todo: isTodo ? 1 : 0, + }, { provisional: true }); + this.props.dispatch({ type: 'NAV_GO', routeName: 'Note', - noteId: null, - folderId: this.props.parentFolderId, - itemType: 'todo', + noteId: newNote.id, }); } + newTodo_press() { + this.newNoteNavigate(this.props.parentFolderId, true); + } + newNote_press() { - this.props.dispatch({ - type: 'NAV_GO', - routeName: 'Note', - noteId: null, - folderId: this.props.parentFolderId, - itemType: 'note', - }); + this.newNoteNavigate(this.props.parentFolderId, false); } render() { diff --git a/ReactNativeClient/lib/components/screens/note.js b/ReactNativeClient/lib/components/screens/note.js index 7258a417cd..39cbd94107 100644 --- a/ReactNativeClient/lib/components/screens/note.js +++ b/ReactNativeClient/lib/components/screens/note.js @@ -99,7 +99,9 @@ class NoteScreenComponent extends BaseScreenComponent { const r = await saveDialog(); if (r) return r; - if (!this.state.note.id) { + const isProvisionalNote = this.props.provisionalNoteIds.includes(this.props.noteId); + + if (isProvisionalNote) { return false; } diff --git a/ReactNativeClient/lib/components/shared/note-screen-shared.js b/ReactNativeClient/lib/components/shared/note-screen-shared.js index 6718f02e4e..82482b290e 100644 --- a/ReactNativeClient/lib/components/shared/note-screen-shared.js +++ b/ReactNativeClient/lib/components/shared/note-screen-shared.js @@ -19,6 +19,20 @@ shared.noteExists = async function(noteId) { return !!existingNote; }; +// Note has been deleted while user was modifying it. In that case, we +// just save a new note so that user can keep editing. +shared.handleNoteDeletedWhileEditing_ = async (note) => { + if (await shared.noteExists(note.id)) return null; + + reg.logger().info('Note has been deleted while it was being edited - recreating it.'); + + let newNote = Object.assign({}, note); + delete newNote.id; + newNote = await Note.save(newNote); + + return Note.load(newNote.id); +}; + shared.saveNoteButton_press = async function(comp, folderId = null, options = null) { options = Object.assign({}, { autoTitle: true, @@ -28,9 +42,8 @@ shared.saveNoteButton_press = async function(comp, folderId = null, options = nu let note = Object.assign({}, comp.state.note); - // Note has been deleted while user was modifying it. In that case, we - // just save a new note by clearing the note ID. - if (note.id && !(await shared.noteExists(note.id))) delete note.id; + const recreatedNote = await shared.handleNoteDeletedWhileEditing_(note); + if (recreatedNote) note = recreatedNote; if (folderId) { note.parent_id = folderId; @@ -60,7 +73,7 @@ shared.saveNoteButton_press = async function(comp, folderId = null, options = nu const stateNote = comp.state.note; // Note was reloaded while being saved. - if (!stateNote || stateNote.id !== savedNote.id) return releaseMutex(); + if (!recreatedNote && (!stateNote || stateNote.id !== savedNote.id)) return releaseMutex(); // Re-assign any property that might have changed during saving (updated_time, etc.) note = Object.assign(note, savedNote); @@ -116,26 +129,18 @@ shared.saveNoteButton_press = async function(comp, folderId = null, options = nu shared.saveOneProperty = async function(comp, name, value) { let note = Object.assign({}, comp.state.note); - // Note has been deleted while user was modifying it. In that, we - // just save a new note by clearing the note ID. - if (note.id && !(await shared.noteExists(note.id))) delete note.id; + const recreatedNote = await shared.handleNoteDeletedWhileEditing_(note); + if (recreatedNote) note = recreatedNote; - // reg.logger().info('Saving note property: ', note.id, name, value); + let toSave = { id: note.id }; + toSave[name] = value; + toSave = await Note.save(toSave); + note[name] = toSave[name]; - if (note.id) { - let toSave = { id: note.id }; - toSave[name] = value; - toSave = await Note.save(toSave); - note[name] = toSave[name]; - - comp.setState({ - lastSavedNote: Object.assign({}, note), - note: note, - }); - } else { - note[name] = value; - comp.setState({ note: note }); - } + comp.setState({ + lastSavedNote: Object.assign({}, note), + note: note, + }); }; shared.noteComponent_change = function(comp, propName, propValue) { @@ -190,14 +195,15 @@ shared.isModified = function(comp) { }; shared.initState = async function(comp) { - let note = null; + const isProvisionalNote = comp.props.provisionalNoteIds.includes(comp.props.noteId); + + const note = await Note.load(comp.props.noteId); let mode = 'view'; - if (!comp.props.noteId) { - note = comp.props.itemType == 'todo' ? Note.newTodo(comp.props.folderId) : Note.new(comp.props.folderId); + + if (isProvisionalNote) { + // note = comp.props.itemType == 'todo' ? Note.newTodo(comp.props.folderId) : Note.new(comp.props.folderId); mode = 'edit'; comp.scheduleFocusUpdate(); - } else { - note = await Note.load(comp.props.noteId); } const folder = Folder.byId(comp.props.folders, note.parent_id); @@ -217,7 +223,7 @@ shared.initState = async function(comp) { } // eslint-disable-next-line require-atomic-updates - comp.lastLoadedNoteId_ = note ? note.id : null; + comp.lastLoadedNoteId_ = note.id; }; shared.toggleIsTodo_onPress = function(comp) { diff --git a/ReactNativeClient/lib/components/shared/reduxSharedMiddleware.js b/ReactNativeClient/lib/components/shared/reduxSharedMiddleware.js index 6010ae74b4..eb4ca59441 100644 --- a/ReactNativeClient/lib/components/shared/reduxSharedMiddleware.js +++ b/ReactNativeClient/lib/components/shared/reduxSharedMiddleware.js @@ -29,10 +29,11 @@ const reduxSharedMiddleware = async function(store, next, action) { refreshTags = true; } - if (action.type === 'NOTE_SELECT') { + if (action.type === 'NOTE_SELECT' || action.type === 'NAV_BACK') { const noteIds = newState.provisionalNoteIds.slice(); for (const noteId of noteIds) { if (action.id === noteId) continue; + reg.logger().info('Provisional was not modified - deleting it'); await Note.delete(noteId); } } diff --git a/ReactNativeClient/main.js b/ReactNativeClient/main.js index 16a69a14a3..e9e8fe0bcf 100644 --- a/ReactNativeClient/main.js +++ b/ReactNativeClient/main.js @@ -12,6 +12,9 @@ import { YellowBox, AppRegistry } from 'react-native'; YellowBox.ignoreWarnings([ 'Require cycle: node_modules/react-native-', 'Require cycle: node_modules/rn-fetch-blob', + 'Warning: componentWillReceiveProps has been renamed', + 'Warning: componentWillUpdate has been renamed', + 'Warning: componentWillMount has been renamed', ]); const { Root } = require('./root.js');