diff --git a/src/public/javascripts/dialogs/options/other.js b/src/public/javascripts/dialogs/options/other.js index 8c79ded40..67114aa57 100644 --- a/src/public/javascripts/dialogs/options/other.js +++ b/src/public/javascripts/dialogs/options/other.js @@ -37,6 +37,20 @@ const TPL = ` +
+

Note erasure timeout

+ +

Deleted notes are at first only marked as deleted and it is possible to recover them + from Recent Notes dialog. After period of time, deleted notes are "erased" which means + their content is not recoverable anymore. This setting allows you to configure the length + of the period between deleting and erasing the note.

+ +
+ + +
+
+

Protected session timeout

@@ -81,6 +95,20 @@ export default class ProtectedSessionOptions { return false; }); + this.$eraseNotesAfterTimeInSeconds = $("#erase-notes-after-time-in-seconds"); + + this.$eraseNotesAfterTimeInSeconds.on('change', () => { + const eraseNotesAfterTimeInSeconds = this.$eraseNotesAfterTimeInSeconds.val(); + + server.put('options', { 'eraseNotesAfterTimeInSeconds': eraseNotesAfterTimeInSeconds }).then(() => { + optionsService.reloadOptions(); + + toastService.showMessage("Options change have been saved."); + }); + + return false; + }); + this.$protectedSessionTimeout = $("#protected-session-timeout-in-seconds"); this.$protectedSessionTimeout.on('change', () => { @@ -126,6 +154,7 @@ export default class ProtectedSessionOptions { this.$spellCheckEnabled.prop("checked", options['spellCheckEnabled'] === 'true'); this.$spellCheckLanguageCode.val(options['spellCheckLanguageCode']); + this.$eraseNotesAfterTimeInSeconds.val(options['eraseNotesAfterTimeInSeconds']); this.$protectedSessionTimeout.val(options['protectedSessionTimeout']); this.$noteRevisionsTimeInterval.val(options['noteRevisionSnapshotTimeInterval']); diff --git a/src/routes/api/options.js b/src/routes/api/options.js index e4edab7b1..17e396906 100644 --- a/src/routes/api/options.js +++ b/src/routes/api/options.js @@ -6,6 +6,7 @@ const attributes = require('../../services/attributes'); // options allowed to be updated directly in options dialog const ALLOWED_OPTIONS = new Set([ + 'eraseNotesAfterTimeInSeconds', 'protectedSessionTimeout', 'noteRevisionSnapshotTimeInterval', 'zoomFactor', diff --git a/src/services/notes.js b/src/services/notes.js index 123b9df9c..3590dfe4f 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -547,7 +547,9 @@ async function scanForLinks(noteId) { } async function eraseDeletedNotes() { - const cutoffDate = new Date(Date.now() - 48 * 3600 * 1000); + const eraseNotesAfterTimeInSeconds = await optionService.getOptionInt('eraseNotesAfterTimeInSeconds'); + + const cutoffDate = new Date(Date.now() - eraseNotesAfterTimeInSeconds * 1000); const noteIdsToErase = await sql.getColumn("SELECT noteId FROM notes WHERE isDeleted = 1 AND isErased = 0 AND notes.utcDateModified <= ?", [dateUtils.utcDateStr(cutoffDate)]); @@ -561,10 +563,11 @@ async function eraseDeletedNotes() { // - we don't want change the hash since this erasing happens on each instance separately // and changing the hash would fire up the sync errors temporarily - // setting contentLength to zero would serve no benefit and it leaves potentially useful trail await sql.executeMany(` UPDATE notes - SET isErased = 1 + SET title = '[deleted]', + contentLength = 0, + isErased = 1 WHERE noteId IN (???)`, noteIdsToErase); await sql.executeMany(` @@ -582,8 +585,15 @@ async function eraseDeletedNotes() { await sql.executeMany(` UPDATE note_revisions SET isErased = 1, - title = NULL + title = NULL, + contentLength = 0 WHERE isErased = 0 AND noteId IN (???)`, noteIdsToErase); + + await sql.executeMany(` + UPDATE attributes + SET name = 'deleted', + value = '' + WHERE noteId IN (???)`, noteIdsToErase); } async function duplicateNote(noteId, parentNoteId) { diff --git a/src/services/options_init.js b/src/services/options_init.js index 98caac718..6cd237c69 100644 --- a/src/services/options_init.js +++ b/src/services/options_init.js @@ -80,7 +80,8 @@ const defaultOptions = [ { name: 'leftPaneWidth', value: '25', isSynced: false }, { name: 'rightPaneWidth', value: '25', isSynced: false }, { name: 'rightPaneVisible', value: 'true', isSynced: false }, - { name: 'nativeTitleBarVisible', value: 'false', isSynced: false } + { name: 'nativeTitleBarVisible', value: 'false', isSynced: false }, + { name: 'eraseNotesAfterTimeInSeconds', value: '604800', isSynced: true } // default is 7 days ]; async function initStartupOptions() {