From 3cfca27b5423b1e6001221e7128d0033aebc83fd Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 2 Jun 2022 17:25:58 +0200 Subject: [PATCH 1/4] expose ability to create note revisions in backend API #2890 --- docs/backend_api/BackendScriptApi.html | 72 ++ docs/backend_api/Note.html | 267 +++++-- docs/backend_api/becca_entities_note.js.html | 37 + .../services_backend_script_api.js.html | 9 + docs/frontend_api/FrontendScriptApi.html | 755 ++++++++++++++---- .../services_frontend_script_api.js.html | 6 +- src/becca/entities/note.js | 37 + src/routes/api/notes.js | 2 +- src/services/note_revisions.js | 41 - src/services/notes.js | 8 +- 10 files changed, 949 insertions(+), 285 deletions(-) diff --git a/docs/backend_api/BackendScriptApi.html b/docs/backend_api/BackendScriptApi.html index d99d0c219..8e1204851 100644 --- a/docs/backend_api/BackendScriptApi.html +++ b/docs/backend_api/BackendScriptApi.html @@ -131,6 +131,78 @@ +

__private :Object

+ + + + +
+ This object contains "at your risk" and "no BC guarantees" objects for advanced use cases. +
+ + + +
Type:
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + +

axios

diff --git a/docs/backend_api/Note.html b/docs/backend_api/Note.html index c5eea4f2f..2afe54588 100644 --- a/docs/backend_api/Note.html +++ b/docs/backend_api/Note.html @@ -93,7 +93,7 @@
Source:
@@ -204,7 +204,7 @@
Source:
@@ -279,7 +279,7 @@
Source:
@@ -347,7 +347,7 @@
Source:
@@ -415,7 +415,7 @@
Source:
@@ -486,7 +486,7 @@
Source:
@@ -554,7 +554,7 @@
Source:
@@ -622,7 +622,7 @@
Source:
@@ -690,7 +690,7 @@
Source:
@@ -758,7 +758,7 @@
Source:
@@ -833,7 +833,7 @@
Source:
@@ -901,7 +901,7 @@
Source:
@@ -969,7 +969,7 @@
Source:
@@ -1037,7 +1037,7 @@
Source:
@@ -1112,7 +1112,7 @@
Source:
@@ -1180,7 +1180,7 @@
Source:
@@ -1248,7 +1248,7 @@
Source:
@@ -1316,7 +1316,7 @@
Source:
@@ -1384,7 +1384,7 @@
Source:
@@ -1452,7 +1452,7 @@
Source:
@@ -1528,7 +1528,7 @@
Source:
@@ -1630,7 +1630,7 @@
Source:
@@ -1830,7 +1830,7 @@
Source:
@@ -1914,7 +1914,7 @@
Source:
@@ -2020,7 +2020,7 @@
Source:
@@ -2194,7 +2194,7 @@
Source:
@@ -2394,7 +2394,7 @@
Source:
@@ -2572,7 +2572,7 @@
Source:
@@ -2683,7 +2683,7 @@
Source:
@@ -2785,7 +2785,7 @@
Source:
@@ -2887,7 +2887,7 @@
Source:
@@ -2989,7 +2989,7 @@
Source:
@@ -3091,7 +3091,7 @@
Source:
@@ -3199,7 +3199,7 @@
Source:
@@ -3305,7 +3305,7 @@
Source:
@@ -3456,7 +3456,7 @@
Source:
@@ -3626,7 +3626,7 @@
Source:
@@ -3781,7 +3781,7 @@
Source:
@@ -3951,7 +3951,7 @@
Source:
@@ -4057,7 +4057,7 @@
Source:
@@ -4259,7 +4259,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -4437,7 +4437,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -4595,7 +4595,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -4765,7 +4765,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -4920,7 +4920,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -5090,7 +5090,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -5245,7 +5245,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -5415,7 +5415,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -5570,7 +5570,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -5679,7 +5679,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -5781,7 +5781,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -5932,7 +5932,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -6102,7 +6102,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -6257,7 +6257,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -6366,7 +6366,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -6475,7 +6475,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -6577,7 +6577,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -6679,7 +6679,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -6781,7 +6781,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -6888,7 +6888,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -6990,7 +6990,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -7141,7 +7141,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -7319,7 +7319,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -7474,7 +7474,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -7629,7 +7629,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -7784,7 +7784,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -7934,7 +7934,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -8040,7 +8040,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -8146,7 +8146,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -8252,7 +8252,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -8358,7 +8358,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -8464,7 +8464,7 @@ This method can be significantly faster than the getAttribute()
Source:
@@ -8856,7 +8856,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
Source:
@@ -9036,7 +9036,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
Source:
@@ -9216,7 +9216,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
Source:
@@ -9363,6 +9363,111 @@ This is a low level method, for notes and branches use `note.deleteNote()` and ' +

saveNoteRevision() → {NoteRevision|null}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +NoteRevision +| + +null + + +
+
+ + + + + + + + + + + + +

setAttribute(type, name, valueopt)

@@ -9538,7 +9643,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
Source:
@@ -9718,7 +9823,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
Source:
@@ -9878,7 +9983,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
Source:
@@ -10120,7 +10225,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
Source:
@@ -10331,7 +10436,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
Source:
@@ -10542,7 +10647,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
Source:
diff --git a/docs/backend_api/becca_entities_note.js.html b/docs/backend_api/becca_entities_note.js.html index 3af1da710..57d0527e7 100644 --- a/docs/backend_api/becca_entities_note.js.html +++ b/docs/backend_api/becca_entities_note.js.html @@ -37,6 +37,8 @@ const entityChangesService = require('../../services/entity_changes'); const AbstractEntity = require("./abstract_entity"); const NoteRevision = require("./note_revision"); const TaskContext = require("../../services/task_context.js"); +const optionService = require("../../services/options.js"); +const noteRevisionService = require("../../services/note_revisions.js"); const LABEL = 'label'; const RELATION = 'relation'; @@ -1192,6 +1194,41 @@ class Note extends AbstractEntity { return !(this.noteId in this.becca.notes); } + /** + * @return {NoteRevision|null} + */ + saveNoteRevision() { + const content = this.getContent(); + + if (!content || (Buffer.isBuffer(content) && content.byteLength === 0)) { + return null; + } + + const contentMetadata = this.getContentMetadata(); + + const noteRevision = new NoteRevision({ + noteId: this.noteId, + // title and text should be decrypted now + title: this.title, + type: this.type, + mime: this.mime, + isProtected: false, // will be fixed in the protectNoteRevisions() call + utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified + ? this.utcDateModified + : contentMetadata.utcDateModified, + utcDateCreated: dateUtils.utcNowDateTime(), + utcDateModified: dateUtils.utcNowDateTime(), + dateLastEdited: this.dateModified > contentMetadata.dateModified + ? this.dateModified + : contentMetadata.dateModified, + dateCreated: dateUtils.localNowDateTime() + }).save(); + + noteRevision.setContent(content); + + return noteRevision; + } + beforeSaving() { super.beforeSaving(); diff --git a/docs/backend_api/services_backend_script_api.js.html b/docs/backend_api/services_backend_script_api.js.html index 3c73eee9f..23c98b39e 100644 --- a/docs/backend_api/services_backend_script_api.js.html +++ b/docs/backend_api/services_backend_script_api.js.html @@ -454,6 +454,15 @@ function BackendScriptApi(currentNote, apiParams) { * @return {{syncVersion, appVersion, buildRevision, dbVersion, dataDirectory, buildDate}|*} - object representing basic info about running Trilium version */ this.getAppInfo = () => appInfo + + /** + * This object contains "at your risk" and "no BC guarantees" objects for advanced use cases. + * + * @type {{becca: Becca}} + */ + this.__private = { + becca + } } module.exports = BackendScriptApi; diff --git a/docs/frontend_api/FrontendScriptApi.html b/docs/frontend_api/FrontendScriptApi.html index 9ac977093..f464ae182 100644 --- a/docs/frontend_api/FrontendScriptApi.html +++ b/docs/frontend_api/FrontendScriptApi.html @@ -1671,7 +1671,7 @@ -

addTextToActiveTabEditor(text)

+

addTextToActiveContextEditor(text)

@@ -1772,7 +1772,146 @@
Source:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

addTextToActiveTabEditor(text)

+ + + + + + +
+ Adds given text to the editor cursor +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
text + + +string + + + + this must be clear text, HTML is not supported.
+ + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • use addTextToActiveContextEditor() instead
+ + + + + + + + + + + +
Source:
+
@@ -1928,7 +2067,7 @@
Source:
@@ -2479,114 +2618,7 @@ -

getActiveNoteDetailWidget() → {Promise.<NoteDetailWidget>}

- - - - - - -
- Get access to the widget handling note detail. Methods like `getWidgetType()` and `getTypeWidget()` to get to the -implementation of actual widget type. -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Promise.<NoteDetailWidget> - - -
-
- - - - - - - - - - - - - -

getActiveTabCodeEditor() → {Promise.<CodeMirror>}

+

getActiveContextCodeEditor() → {Promise.<CodeMirror>}

@@ -2638,7 +2670,7 @@ implementation of actual widget type.
Source:
@@ -2696,7 +2728,7 @@ implementation of actual widget type. -

getActiveTabNote() → {NoteShort}

+

getActiveContextNote() → {NoteShort}

@@ -2744,7 +2776,438 @@ implementation of actual widget type.
Source:
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+ active note (loaded into right pane) +
+ + + +
+
+ Type +
+
+ +NoteShort + + +
+
+ + + + + + + + + + + + + +

getActiveContextNotePath() → {Promise.<(string|null)>}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+ returns note path of active note or null if there isn't active note +
+ + + +
+
+ Type +
+
+ +Promise.<(string|null)> + + +
+
+ + + + + + + + + + + + + +

getActiveContextTextEditor() → {Promise.<CKEditor>}

+ + + + + + +
+ See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance. +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+ instance of CKEditor +
+ + + +
+
+ Type +
+
+ +Promise.<CKEditor> + + +
+
+ + + + + + + + + + + + + +

getActiveNoteDetailWidget() → {Promise.<NoteDetailWidget>}

+ + + + + + +
+ Get access to the widget handling note detail. Methods like `getWidgetType()` and `getTypeWidget()` to get to the +implementation of actual widget type. +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<NoteDetailWidget> + + +
+
+ + + + + + + + + + + + + +

getActiveTabNote() → {NoteShort}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • use getActiveContextNote() instead
+ + + + + + + + + + + +
Source:
+
@@ -2838,6 +3301,8 @@ implementation of actual widget type. +
Deprecated:
  • use getActiveContextNotePath() instead
+ @@ -2850,7 +3315,7 @@ implementation of actual widget type.
Source:
@@ -2908,7 +3373,7 @@ implementation of actual widget type. -

getActiveTabTextEditor(callbackopt) → {Promise.<CKEditor>}

+

getActiveTabTextEditor(callbackopt)

@@ -2975,7 +3440,7 @@ implementation of actual widget type. - deprecated (use returned promise): callback receiving "textEditor" instance + callback receiving "textEditor" instance @@ -3004,6 +3469,8 @@ implementation of actual widget type. +
Deprecated:
  • use getActiveContextTextEditor()
+ @@ -3016,7 +3483,7 @@ implementation of actual widget type.
Source:
@@ -3041,28 +3508,6 @@ implementation of actual widget type. -
Returns:
- - -
- instance of CKEditor -
- - - -
-
- Type -
-
- -Promise.<CKEditor> - - -
-
- - @@ -3175,7 +3620,7 @@ implementation of actual widget type.
Source:
@@ -3332,7 +3777,7 @@ implementation of actual widget type.
Source:
@@ -3487,7 +3932,7 @@ implementation of actual widget type.
Source:
@@ -3749,7 +4194,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -4212,7 +4657,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -4367,7 +4812,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -4522,7 +4967,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -4959,7 +5404,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -5115,7 +5560,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -5271,7 +5716,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -5408,7 +5853,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -5562,7 +6007,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -6503,7 +6948,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -6654,7 +7099,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -7340,7 +7785,7 @@ Typical use case is when new note has been created, we should wait until it is s
Source:
diff --git a/docs/frontend_api/services_frontend_script_api.js.html b/docs/frontend_api/services_frontend_script_api.js.html index fe896a184..0bb38dc24 100644 --- a/docs/frontend_api/services_frontend_script_api.js.html +++ b/docs/frontend_api/services_frontend_script_api.js.html @@ -412,7 +412,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain this.getActiveTabTextEditor = callback => { console.warn("api.getActiveTabTextEditor() is deprecated, use getActiveContextTextEditor() instead."); - return appContext.tabManager.getActiveContextTextEditor(callback); + return appContext.tabManager.getActiveContext()?.getTextEditor(callback); }; /** @@ -421,7 +421,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain * @method * @returns {Promise<CKEditor>} instance of CKEditor */ - this.getActiveContextTextEditor = () => appContext.tabManager.getActiveContextTextEditor(); + this.getActiveContextTextEditor = () => appContext.tabManager.getActiveContext()?.getTextEditor(); /** * See https://codemirror.net/doc/manual.html#api @@ -429,7 +429,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain * @method * @returns {Promise<CodeMirror>} instance of CodeMirror */ - this.getActiveContextCodeEditor = () => appContext.tabManager.getActiveContextCodeEditor(); + this.getActiveContextCodeEditor = () => appContext.tabManager.getActiveContext()?.getCodeEditor(); /** * Get access to the widget handling note detail. Methods like `getWidgetType()` and `getTypeWidget()` to get to the diff --git a/src/becca/entities/note.js b/src/becca/entities/note.js index 595e41052..a815df1c3 100644 --- a/src/becca/entities/note.js +++ b/src/becca/entities/note.js @@ -9,6 +9,8 @@ const entityChangesService = require('../../services/entity_changes'); const AbstractEntity = require("./abstract_entity"); const NoteRevision = require("./note_revision"); const TaskContext = require("../../services/task_context.js"); +const optionService = require("../../services/options.js"); +const noteRevisionService = require("../../services/note_revisions.js"); const LABEL = 'label'; const RELATION = 'relation'; @@ -1164,6 +1166,41 @@ class Note extends AbstractEntity { return !(this.noteId in this.becca.notes); } + /** + * @return {NoteRevision|null} + */ + saveNoteRevision() { + const content = this.getContent(); + + if (!content || (Buffer.isBuffer(content) && content.byteLength === 0)) { + return null; + } + + const contentMetadata = this.getContentMetadata(); + + const noteRevision = new NoteRevision({ + noteId: this.noteId, + // title and text should be decrypted now + title: this.title, + type: this.type, + mime: this.mime, + isProtected: false, // will be fixed in the protectNoteRevisions() call + utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified + ? this.utcDateModified + : contentMetadata.utcDateModified, + utcDateCreated: dateUtils.utcNowDateTime(), + utcDateModified: dateUtils.utcNowDateTime(), + dateLastEdited: this.dateModified > contentMetadata.dateModified + ? this.dateModified + : contentMetadata.dateModified, + dateCreated: dateUtils.localNowDateTime() + }).save(); + + noteRevision.setContent(content); + + return noteRevision; + } + beforeSaving() { super.beforeSaving(); diff --git a/src/routes/api/notes.js b/src/routes/api/notes.js index 5f334edc8..272cc88e0 100644 --- a/src/routes/api/notes.js +++ b/src/routes/api/notes.js @@ -206,7 +206,7 @@ function changeTitle(req) { const noteTitleChanged = note.title !== title; if (noteTitleChanged) { - noteService.saveNoteRevision(note); + noteService.saveNoteRevisionIfNeeded(note); } note.title = title; diff --git a/src/services/note_revisions.js b/src/services/note_revisions.js index 3ff9b692a..3759d2d2e 100644 --- a/src/services/note_revisions.js +++ b/src/services/note_revisions.js @@ -30,46 +30,6 @@ function protectNoteRevisions(note) { } } -/** - * @param {Note} note - * @return {NoteRevision|null} - */ -function createNoteRevision(note) { - if (note.hasLabel("disableVersioning")) { - return null; - } - - const content = note.getContent(); - - if (!content || (Buffer.isBuffer(content) && content.byteLength === 0)) { - return null; - } - - const contentMetadata = note.getContentMetadata(); - - const noteRevision = new NoteRevision({ - noteId: note.noteId, - // title and text should be decrypted now - title: note.title, - type: note.type, - mime: note.mime, - isProtected: false, // will be fixed in the protectNoteRevisions() call - utcDateLastEdited: note.utcDateModified > contentMetadata.utcDateModified - ? note.utcDateModified - : contentMetadata.utcDateModified, - utcDateCreated: dateUtils.utcNowDateTime(), - utcDateModified: dateUtils.utcNowDateTime(), - dateLastEdited: note.dateModified > contentMetadata.dateModified - ? note.dateModified - : contentMetadata.dateModified, - dateCreated: dateUtils.localNowDateTime() - }).save(); - - noteRevision.setContent(content); - - return noteRevision; -} - function eraseNoteRevisions(noteRevisionIdsToErase) { if (noteRevisionIdsToErase.length === 0) { return; @@ -86,6 +46,5 @@ function eraseNoteRevisions(noteRevisionIdsToErase) { module.exports = { protectNoteRevisions, - createNoteRevision, eraseNoteRevisions }; diff --git a/src/services/notes.js b/src/services/notes.js index 5e3670727..15526e9b6 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -491,7 +491,7 @@ function saveLinks(note, content) { return content; } -function saveNoteRevision(note) { +function saveNoteRevisionIfNeeded(note) { // files and images are versioned separately if (note.type === 'file' || note.type === 'image' || note.hasLabel('disableVersioning')) { return; @@ -508,7 +508,7 @@ function saveNoteRevision(note) { const msSinceDateCreated = now.getTime() - dateUtils.parseDateTime(note.utcDateCreated).getTime(); if (!existingNoteRevisionId && msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) { - noteRevisionService.createNoteRevision(note); + note.saveNoteRevision(); } } @@ -519,7 +519,7 @@ function updateNote(noteId, noteUpdates) { throw new Error(`Note '${noteId}' is not available for change!`); } - saveNoteRevision(note); + saveNoteRevisionIfNeeded(note); // if protected status changed, then we need to encrypt/decrypt the content anyway if (['file', 'image'].includes(note.type) && note.isProtected !== noteUpdates.isProtected) { @@ -910,6 +910,6 @@ module.exports = { triggerNoteTitleChanged, eraseDeletedNotesNow, eraseNotesWithDeleteId, - saveNoteRevision, + saveNoteRevisionIfNeeded, downloadImages }; From 7fa531b3d65e73ed08cd8eb310da2640a8e43ce6 Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 2 Jun 2022 17:36:30 +0200 Subject: [PATCH 2/4] add openSplitWithNote() frontend api method, #2891 --- docs/frontend_api/FrontendScriptApi.html | 264 +++++++++++++++--- docs/frontend_api/global.html | 2 +- .../services_frontend_script_api.js.html | 20 ++ .../app/services/frontend_script_api.js | 20 ++ 4 files changed, 262 insertions(+), 44 deletions(-) diff --git a/docs/frontend_api/FrontendScriptApi.html b/docs/frontend_api/FrontendScriptApi.html index f464ae182..a6b3044b7 100644 --- a/docs/frontend_api/FrontendScriptApi.html +++ b/docs/frontend_api/FrontendScriptApi.html @@ -1635,7 +1635,7 @@
Source:
@@ -1772,7 +1772,7 @@
Source:
@@ -1911,7 +1911,7 @@
Source:
@@ -2067,7 +2067,7 @@
Source:
@@ -2427,7 +2427,7 @@
Source:
@@ -2560,7 +2560,7 @@
Source:
@@ -2670,7 +2670,7 @@
Source:
@@ -2776,7 +2776,7 @@
Source:
@@ -2882,7 +2882,7 @@
Source:
@@ -2992,7 +2992,7 @@
Source:
@@ -3103,7 +3103,7 @@ implementation of actual widget type.
Source:
@@ -3207,7 +3207,7 @@ implementation of actual widget type.
Source:
@@ -3315,7 +3315,7 @@ implementation of actual widget type.
Source:
@@ -3483,7 +3483,7 @@ implementation of actual widget type.
Source:
@@ -3620,7 +3620,7 @@ implementation of actual widget type.
Source:
@@ -3777,7 +3777,7 @@ implementation of actual widget type.
Source:
@@ -3932,7 +3932,7 @@ implementation of actual widget type.
Source:
@@ -4039,7 +4039,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -4194,7 +4194,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -4350,7 +4350,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -4551,7 +4551,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -4657,7 +4657,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -4812,7 +4812,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -4967,7 +4967,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -5021,6 +5021,184 @@ otherwise (by e.g. createNoteLink()) +

openSplitWithNote(notePath, activate) → {Promise.<void>}

+ + + + + + +
+ Open a note in a new split. +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
notePath + + +string + + + + (or noteId)
activate + + +boolean + + + + set to true to activate the new split, false to stay on the current split
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<void> + + +
+
+ + + + + + + + + + + + +

openTabWithNote(notePath, activate) → {Promise.<void>}

@@ -5296,7 +5474,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -5404,7 +5582,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -5560,7 +5738,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -5716,7 +5894,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -5853,7 +6031,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -6007,7 +6185,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -6093,7 +6271,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -6230,7 +6408,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -6391,7 +6569,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -6499,7 +6677,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -6637,7 +6815,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -6793,7 +6971,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -6948,7 +7126,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -7099,7 +7277,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -7236,7 +7414,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -7373,7 +7551,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -7533,7 +7711,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -7693,7 +7871,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -7785,7 +7963,7 @@ Typical use case is when new note has been created, we should wait until it is s
Source:
diff --git a/docs/frontend_api/global.html b/docs/frontend_api/global.html index e3bb5cbf0..8879721e8 100644 --- a/docs/frontend_api/global.html +++ b/docs/frontend_api/global.html @@ -395,7 +395,7 @@
Source:
diff --git a/docs/frontend_api/services_frontend_script_api.js.html b/docs/frontend_api/services_frontend_script_api.js.html index 0bb38dc24..da00296e1 100644 --- a/docs/frontend_api/services_frontend_script_api.js.html +++ b/docs/frontend_api/services_frontend_script_api.js.html @@ -129,6 +129,26 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain } }; + /** + * Open a note in a new split. + * + * @param {string} notePath (or noteId) + * @param {boolean} activate - set to true to activate the new split, false to stay on the current split + * @return {Promise<void>} + */ + this.openSplitWithNote = async (notePath, activate) => { + await ws.waitForMaxKnownEntityChangeId(); + + const subContexts = appContext.tabManager.getActiveContext().getSubContexts(); + const {ntxId} = subContexts[subContexts.length - 1]; + + appContext.triggerCommand("openNewNoteSplit", {ntxId, notePath}); + + if (activate) { + appContext.triggerEvent('focusAndSelectTitle'); + } + }; + /** * @typedef {Object} ToolbarButtonOptions * @property {string} title diff --git a/src/public/app/services/frontend_script_api.js b/src/public/app/services/frontend_script_api.js index b2eabdc13..5ae0eaa05 100644 --- a/src/public/app/services/frontend_script_api.js +++ b/src/public/app/services/frontend_script_api.js @@ -101,6 +101,26 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain } }; + /** + * Open a note in a new split. + * + * @param {string} notePath (or noteId) + * @param {boolean} activate - set to true to activate the new split, false to stay on the current split + * @return {Promise} + */ + this.openSplitWithNote = async (notePath, activate) => { + await ws.waitForMaxKnownEntityChangeId(); + + const subContexts = appContext.tabManager.getActiveContext().getSubContexts(); + const {ntxId} = subContexts[subContexts.length - 1]; + + appContext.triggerCommand("openNewNoteSplit", {ntxId, notePath}); + + if (activate) { + appContext.triggerEvent('focusAndSelectTitle'); + } + }; + /** * @typedef {Object} ToolbarButtonOptions * @property {string} title From 0a4f419e5e86077e7b47566d85c85e166f423e4e Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 2 Jun 2022 17:41:23 +0200 Subject: [PATCH 3/4] fix when searching for "note.", closes #2889 --- src/services/search/services/lex.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/search/services/lex.js b/src/services/search/services/lex.js index c6bdc2dfd..470ba5526 100644 --- a/src/services/search/services/lex.js +++ b/src/services/search/services/lex.js @@ -83,7 +83,7 @@ function lex(str) { continue; } else if (!quotes) { - if (!fulltextEnded && currentWord === 'note' && chr === '.') { + if (!fulltextEnded && currentWord === 'note' && chr === '.' && i + 1 < str.length) { fulltextEnded = true; } From 15a9ff44500da3d52f489d8823320d1c49dbaaa8 Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 2 Jun 2022 22:28:25 +0200 Subject: [PATCH 4/4] when closing / clearing last tab, close all splits --- src/public/app/services/tab_manager.js | 42 ++++++++++++++++++++------ src/public/app/widgets/note_detail.js | 2 +- src/public/app/widgets/note_title.js | 2 +- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/public/app/services/tab_manager.js b/src/public/app/services/tab_manager.js index 15f939bfe..59318d6e3 100644 --- a/src/public/app/services/tab_manager.js +++ b/src/public/app/services/tab_manager.js @@ -306,7 +306,8 @@ export default class TabManager extends Component { const mainNoteContexts = this.getNoteContexts().filter(nc => nc.isMainContext()); if (mainNoteContexts.length === 1) { - mainNoteContexts[0].setEmpty(); + await this.clearLastMainNoteContext(noteContextToRemove); + return; } } @@ -317,7 +318,7 @@ export default class TabManager extends Component { const noteContextsToRemove = noteContextToRemove.getSubContexts(); const ntxIdsToRemove = noteContextsToRemove.map(nc => nc.ntxId); - await this.triggerEvent('beforeTabRemove', { ntxIds: ntxIdsToRemove }); + await this.triggerEvent('beforeNoteContextRemove', { ntxIds: ntxIdsToRemove }); if (!noteContextToRemove.isMainContext()) { await this.activateNoteContext(noteContextToRemove.getMainContext().ntxId); @@ -336,16 +337,39 @@ export default class TabManager extends Component { } } - this.children = this.children.filter(nc => !ntxIdsToRemove.includes(nc.ntxId)); - - this.recentlyClosedTabs.push(noteContextsToRemove); - - this.triggerEvent('noteContextRemoved', {ntxIds: ntxIdsToRemove}); - - this.tabsUpdate.scheduleUpdate(); + this.removeNoteContexts(noteContextsToRemove); }); } + async clearLastMainNoteContext(noteContextToClear) { + noteContextToClear.setEmpty(); + + // activate main split + await this.activateNoteContext(noteContextToClear.ntxId); + + // remove all other splits + const noteContextsToRemove = noteContextToClear.getSubContexts() + .filter(ntx => ntx.ntxId !== noteContextToClear.ntxId); + + const ntxIdsToRemove = noteContextsToRemove.map(ntx => ntx.ntxId); + + await this.triggerEvent('beforeNoteContextRemove', {ntxIds: ntxIdsToRemove}); + + this.removeNoteContexts(noteContextsToRemove); + } + + removeNoteContexts(noteContextsToRemove) { + const ntxIdsToRemove = noteContextsToRemove.map(nc => nc.ntxId); + + this.children = this.children.filter(nc => !ntxIdsToRemove.includes(nc.ntxId)); + + this.recentlyClosedTabs.push(noteContextsToRemove); + + this.triggerEvent('noteContextRemoved', {ntxIds: ntxIdsToRemove}); + + this.tabsUpdate.scheduleUpdate(); + } + tabReorderEvent({ntxIdsInOrder}) { const order = {}; diff --git a/src/public/app/widgets/note_detail.js b/src/public/app/widgets/note_detail.js index 0a0790fa8..9027852c1 100644 --- a/src/public/app/widgets/note_detail.js +++ b/src/public/app/widgets/note_detail.js @@ -216,7 +216,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { } } - async beforeTabRemoveEvent({ntxIds}) { + async beforeNoteContextRemoveEvent({ntxIds}) { if (this.isNoteContext(ntxIds)) { await this.spacedUpdate.updateNowIfNecessary(); } diff --git a/src/public/app/widgets/note_title.js b/src/public/app/widgets/note_title.js index 59007faa6..2cbd9b5a1 100644 --- a/src/public/app/widgets/note_title.js +++ b/src/public/app/widgets/note_title.js @@ -87,7 +87,7 @@ export default class NoteTitleWidget extends NoteContextAwareWidget { } } - async beforeTabRemoveEvent({ntxIds}) { + async beforeNoteContextRemoveEvent({ntxIds}) { if (this.isNoteContext(ntxIds)) { await this.spacedUpdate.updateNowIfNecessary(); }