From 18416a30fdf85ac8caded731da475c480ad4ac1f Mon Sep 17 00:00:00 2001 From: korelstar Date: Sat, 27 Jun 2020 17:59:32 +0200 Subject: [PATCH 1/3] debounce autotitle --- appinfo/routes.php | 6 ++++++ lib/Controller/NotesController.php | 24 +++++++++++++++++------ src/NotesService.js | 14 +++++++++++++- src/components/Note.vue | 31 +++++++++++++++++++++++++++--- src/store/notes.js | 1 - 5 files changed, 65 insertions(+), 11 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index 1c43732bc..90e673896 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -43,6 +43,12 @@ 'url' => '/notes/undo', 'verb' => 'POST', ], + [ + 'name' => 'notes#autotitle', + 'url' => '/notes/{id}/autotitle', + 'verb' => 'PUT', + 'requirements' => ['id' => '\d+'], + ], [ 'name' => 'notes#update', 'url' => '/notes/{id}', diff --git a/lib/Controller/NotesController.php b/lib/Controller/NotesController.php index f99123a4b..714ca7d99 100644 --- a/lib/Controller/NotesController.php +++ b/lib/Controller/NotesController.php @@ -191,14 +191,26 @@ public function undo( /** * @NoAdminRequired */ - public function update(int $id, string $content, bool $autotitle) : JSONResponse { - return $this->helper->handleErrorResponse(function () use ($id, $content, $autotitle) { + public function autotitle(int $id) : JSONResponse { + return $this->helper->handleErrorResponse(function () use ($id) { $note = $this->notesService->get($this->helper->getUID(), $id); - $note->setContent($content); - if ($autotitle) { - $title = $this->notesService->getTitleFromContent($content); - $note->setTitle($title); + $oldTitle = $note->getTitle(); + $newTitle = $this->notesService->getTitleFromContent($note->getContent()); + if ($oldTitle !== $newTitle) { + $note->setTitle($newTitle); } + return $note->getTitle(); + }); + } + + + /** + * @NoAdminRequired + */ + public function update(int $id, string $content) : JSONResponse { + return $this->helper->handleErrorResponse(function () use ($id, $content) { + $note = $this->notesService->get($this->helper->getUID(), $id); + $note->setContent($content); return $note->getData(); }); } diff --git a/src/NotesService.js b/src/NotesService.js index 2feca408c..a20a5a973 100644 --- a/src/NotesService.js +++ b/src/NotesService.js @@ -167,7 +167,7 @@ export const createNote = category => { function _updateNote(note) { return axios - .put(url('/notes/' + note.id), { content: note.content, autotitle: note.autotitle }) + .put(url('/notes/' + note.id), { content: note.content }) .then(response => { const updated = response.data note.saveError = false @@ -186,6 +186,18 @@ function _updateNote(note) { }) } +export const autotitleNote = noteId => { + return axios + .put(url('/notes/' + noteId + '/autotitle')) + .then((response) => { + store.commit('setNoteAttribute', { noteId: noteId, attribute: 'title', value: response.data }) + }) + .catch(err => { + console.error(err) + handleSyncError(t('notes', 'Updating title for note {id} has failed.', { id: noteId }), err) + }) +} + export const undoDeleteNote = (note) => { return axios .post(url('/notes/undo'), note) diff --git a/src/components/Note.vue b/src/components/Note.vue index 68b8d5584..310906277 100644 --- a/src/components/Note.vue +++ b/src/components/Note.vue @@ -63,7 +63,7 @@ import { import { showError } from '@nextcloud/dialogs' import { emit } from '@nextcloud/event-bus' -import { fetchNote, refreshNote, saveNote, saveNoteManually, routeIsNewNote } from '../NotesService' +import { fetchNote, refreshNote, saveNote, saveNoteManually, autotitleNote, routeIsNewNote } from '../NotesService' import TheEditor from './EditorEasyMDE' import ThePreview from './EditorMarkdownIt' import store from '../store' @@ -99,6 +99,7 @@ export default { preview: false, actionsOpen: false, autosaveTimer: null, + autotitleTimer: null, refreshTimer: null, etag: null, } @@ -111,6 +112,9 @@ export default { title() { return this.note ? this.note.title : '' }, + isNewNote() { + return routeIsNewNote(this.$route) + }, isManualSave() { return store.state.app.isManualSave }, @@ -260,18 +264,40 @@ export default { ...this.note, content: newContent, unsaved: true, - autotitle: routeIsNewNote(this.$route), } store.commit('updateNote', note) this.$forceUpdate() + + // queue auto saving note content if (this.autosaveTimer === null) { this.autosaveTimer = setTimeout(() => { this.autosaveTimer = null saveNote(note.id) }, 2000) } + + // (re-) start auto refresh timer // TODO should be after save is finished this.startRefreshTimer() + + // stop old autotitle timer + if (this.autotitleTimer !== null) { + console.debug('clear autotitle timer') + clearTimeout(this.autotitleTimer) + this.autotitleTimer = null + } + // start autotitle timer if note is new + if (this.isNewNote) { + console.debug('start autotitle timer') + this.autotitleTimer = setTimeout(() => { + console.debug('execute autotitle timer') + this.autotitleTimer = null + if (this.isNewNote) { + console.debug('autotitle note') + autotitleNote(note.id) + } + }, 5000) + } } }, @@ -293,7 +319,6 @@ export default { onManualSave() { const note = { ...this.note, - autotitle: routeIsNewNote(this.$route), } store.commit('add', note) saveNoteManually(this.note.id) diff --git a/src/store/notes.js b/src/store/notes.js index 88393aa8b..621d9be85 100644 --- a/src/store/notes.js +++ b/src/store/notes.js @@ -83,7 +83,6 @@ const mutations = { // don't update meta-data over full data if (updated.content !== undefined || note.content === undefined) { note.content = updated.content - Vue.set(note, 'autotitle', updated.autotitle) Vue.set(note, 'unsaved', updated.unsaved) Vue.set(note, 'error', updated.error) Vue.set(note, 'errorMessage', updated.errorMessage) From bd6e743f0ab2b19dac32cacd38968e695b975d30 Mon Sep 17 00:00:00 2001 From: korelstar Date: Sat, 27 Jun 2020 22:48:29 +0200 Subject: [PATCH 2/3] create central config for interval definitions --- src/components/Note.vue | 11 ++++------- src/config.js | 9 +++++++++ 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 src/config.js diff --git a/src/components/Note.vue b/src/components/Note.vue index 310906277..c3cdec24e 100644 --- a/src/components/Note.vue +++ b/src/components/Note.vue @@ -63,6 +63,7 @@ import { import { showError } from '@nextcloud/dialogs' import { emit } from '@nextcloud/event-bus' +import { config } from '../config' import { fetchNote, refreshNote, saveNote, saveNoteManually, autotitleNote, routeIsNewNote } from '../NotesService' import TheEditor from './EditorEasyMDE' import ThePreview from './EditorMarkdownIt' @@ -244,7 +245,7 @@ export default { this.refreshTimer = setTimeout(() => { this.refreshTimer = null this.refreshNote() - }, 10000) + }, config.interval.note.refresh * 1000) }, refreshNote() { @@ -273,7 +274,7 @@ export default { this.autosaveTimer = setTimeout(() => { this.autosaveTimer = null saveNote(note.id) - }, 2000) + }, config.interval.note.autosave * 1000) } // (re-) start auto refresh timer @@ -282,21 +283,17 @@ export default { // stop old autotitle timer if (this.autotitleTimer !== null) { - console.debug('clear autotitle timer') clearTimeout(this.autotitleTimer) this.autotitleTimer = null } // start autotitle timer if note is new if (this.isNewNote) { - console.debug('start autotitle timer') this.autotitleTimer = setTimeout(() => { - console.debug('execute autotitle timer') this.autotitleTimer = null if (this.isNewNote) { - console.debug('autotitle note') autotitleNote(note.id) } - }, 5000) + }, config.interval.note.autotitle * 1000) } } }, diff --git a/src/config.js b/src/config.js new file mode 100644 index 000000000..711ee31d1 --- /dev/null +++ b/src/config.js @@ -0,0 +1,9 @@ +export const config = { + interval: { + note: { + autosave: 1, + autotitle: 2, + refresh: 10, + }, + }, +} From cd1dd7aee23b3924e027e3cea9e79a6c5e965fa6 Mon Sep 17 00:00:00 2001 From: korelstar Date: Sun, 28 Jun 2020 08:07:24 +0200 Subject: [PATCH 3/3] fix unnecessary error messages / linting --- lib/Controller/NotesController.php | 2 +- src/App.vue | 4 +++- src/components/Note.vue | 15 ++++----------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/lib/Controller/NotesController.php b/lib/Controller/NotesController.php index 714ca7d99..98775937d 100644 --- a/lib/Controller/NotesController.php +++ b/lib/Controller/NotesController.php @@ -79,7 +79,7 @@ public function index(int $pruneBefore = 0) : JSONResponse { return $note->getData([ 'content' ]); } }, $data['notes']); - if ($lastViewedNote) { + if ($lastViewedNote && !$pruneBefore) { // check if note exists try { $this->notesService->get($userId, $lastViewedNote); diff --git a/src/App.vue b/src/App.vue index cc4378f26..c6d0f1d52 100644 --- a/src/App.vue +++ b/src/App.vue @@ -180,7 +180,9 @@ export default { if (availableNotes.length > 0) { this.routeToNote(availableNotes[0].id) } else { - this.$router.push({ name: 'welcome' }) + if (this.$route.name !== 'welcome') { + this.$router.push({ name: 'welcome' }) + } } }, diff --git a/src/components/Note.vue b/src/components/Note.vue index c3cdec24e..69111ef08 100644 --- a/src/components/Note.vue +++ b/src/components/Note.vue @@ -20,19 +20,12 @@ > {{ t('notes', 'Details') }} - - {{ t('notes', 'Preview') }} - - - {{ t('notes', 'Edit') }} + {{ preview ? t('notes', 'Edit') : t('notes', 'Preview') }}