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..a6b3044b7 100644
--- a/docs/frontend_api/FrontendScriptApi.html
+++ b/docs/frontend_api/FrontendScriptApi.html
@@ -1635,7 +1635,144 @@
Source:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ addTextToActiveContextEditor(text)
+
+
+
+
+
+
+
+ Adds given text to the editor cursor
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name |
+
+
+ Type |
+
+
+
+
+
+ Description |
+
+
+
+
+
+
+
+
+ text |
+
+
+
+
+
+string
+
+
+
+ |
+
+
+
+
+
+ this must be clear text, HTML is not supported. |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+
@@ -1760,6 +1897,8 @@
+ - Deprecated:
- use addTextToActiveContextEditor() instead
+
@@ -1772,7 +1911,7 @@
- Source:
@@ -1928,7 +2067,7 @@
- Source:
@@ -2288,7 +2427,7 @@
- Source:
@@ -2421,7 +2560,7 @@
- Source:
@@ -2479,6 +2618,438 @@
+ getActiveContextCodeEditor() → {Promise.<CodeMirror>}
+
+
+
+
+
+
+
+ See https://codemirror.net/doc/manual.html#api
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Source:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+ instance of CodeMirror
+
+
+
+
+
+ -
+ Type
+
+ -
+
+Promise.<CodeMirror>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getActiveContextNote() → {NoteShort}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - 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>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2532,7 +3103,7 @@ implementation of actual widget type.
- Source:
@@ -2586,116 +3157,6 @@ implementation of actual widget type.
- getActiveTabCodeEditor() → {Promise.<CodeMirror>}
-
-
-
-
-
-
-
- See https://codemirror.net/doc/manual.html#api
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - Source:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Returns:
-
-
-
- instance of CodeMirror
-
-
-
-
-
- -
- Type
-
- -
-
-Promise.<CodeMirror>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
getActiveTabNote() → {NoteShort}
@@ -2732,6 +3193,8 @@ implementation of actual widget type.
+ - Deprecated:
- use getActiveContextNote() instead
+
@@ -2744,7 +3207,7 @@ implementation of actual widget type.
- 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:
@@ -3594,7 +4039,7 @@ if some action needs to happen on only one specific instance.
- Source:
@@ -3749,7 +4194,7 @@ if some action needs to happen on only one specific instance.
- Source:
@@ -3905,7 +4350,7 @@ if some action needs to happen on only one specific instance.
- Source:
@@ -4106,7 +4551,7 @@ otherwise (by e.g. createNoteLink())
- 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:
@@ -4576,6 +5021,184 @@ otherwise (by e.g. createNoteLink())
+ openSplitWithNote(notePath, activate) → {Promise.<void>}
+
+
+
+
+
+
+
+ Open a note in a new split.
+
+
+
+
+
+
+
+
+
+
+ Parameters:
+
+
+
+
+
+
+ Name |
+
+
+ Type |
+
+
+
+
+
+ Description |
+
+
+
+
+
+
+
+
+ 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>}
@@ -4851,7 +5474,7 @@ otherwise (by e.g. createNoteLink())
- Source:
@@ -4959,7 +5582,7 @@ otherwise (by e.g. createNoteLink())
- Source:
@@ -5115,7 +5738,7 @@ otherwise (by e.g. createNoteLink())
- Source:
@@ -5271,7 +5894,7 @@ otherwise (by e.g. createNoteLink())
- Source:
@@ -5408,7 +6031,7 @@ otherwise (by e.g. createNoteLink())
- Source:
@@ -5562,7 +6185,7 @@ otherwise (by e.g. createNoteLink())
- Source:
@@ -5648,7 +6271,7 @@ otherwise (by e.g. createNoteLink())
- Source:
@@ -5785,7 +6408,7 @@ otherwise (by e.g. createNoteLink())
- Source:
@@ -5946,7 +6569,7 @@ Internally this serializes the anonymous function into string and sends it to ba
- Source:
@@ -6054,7 +6677,7 @@ Internally this serializes the anonymous function into string and sends it to ba
- Source:
@@ -6192,7 +6815,7 @@ Internally this serializes the anonymous function into string and sends it to ba
- Source:
@@ -6348,7 +6971,7 @@ Internally this serializes the anonymous function into string and sends it to ba
- Source:
@@ -6503,7 +7126,7 @@ Internally this serializes the anonymous function into string and sends it to ba
- Source:
@@ -6654,7 +7277,7 @@ Internally this serializes the anonymous function into string and sends it to ba
- Source:
@@ -6791,7 +7414,7 @@ Internally this serializes the anonymous function into string and sends it to ba
- Source:
@@ -6928,7 +7551,7 @@ Internally this serializes the anonymous function into string and sends it to ba
- Source:
@@ -7088,7 +7711,7 @@ Internally this serializes the anonymous function into string and sends it to ba
- Source:
@@ -7248,7 +7871,7 @@ Internally this serializes the anonymous function into string and sends it to ba
- Source:
@@ -7340,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 fe896a184..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
@@ -412,7 +432,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 +441,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 +449,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/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
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 f5dc0093b..d6bf8fe16 100644
--- a/src/public/app/widgets/note_detail.js
+++ b/src/public/app/widgets/note_detail.js
@@ -219,7 +219,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();
}
diff --git a/src/routes/api/notes.js b/src/routes/api/notes.js
index 2b7ccf595..a2aef1dfa 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 8168dc0de..69633c681 100644
--- a/src/services/notes.js
+++ b/src/services/notes.js
@@ -499,7 +499,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;
@@ -516,7 +516,7 @@ function saveNoteRevision(note) {
const msSinceDateCreated = now.getTime() - dateUtils.parseDateTime(note.utcDateCreated).getTime();
if (!existingNoteRevisionId && msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) {
- noteRevisionService.createNoteRevision(note);
+ note.saveNoteRevision();
}
}
@@ -527,7 +527,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) {
@@ -918,6 +918,6 @@ module.exports = {
triggerNoteTitleChanged,
eraseDeletedNotesNow,
eraseNotesWithDeleteId,
- saveNoteRevision,
+ saveNoteRevisionIfNeeded,
downloadImages
};
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;
}