mirror of
https://github.com/zadam/trilium.git
synced 2025-11-11 07:45:51 +01:00
Merge branch 'master' into next53
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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<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
|
||||
|
||||
@@ -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 = {};
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
|
||||
}
|
||||
}
|
||||
|
||||
async beforeTabRemoveEvent({ntxIds}) {
|
||||
async beforeNoteContextRemoveEvent({ntxIds}) {
|
||||
if (this.isNoteContext(ntxIds)) {
|
||||
await this.spacedUpdate.updateNowIfNecessary();
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ export default class NoteTitleWidget extends NoteContextAwareWidget {
|
||||
}
|
||||
}
|
||||
|
||||
async beforeTabRemoveEvent({ntxIds}) {
|
||||
async beforeNoteContextRemoveEvent({ntxIds}) {
|
||||
if (this.isNoteContext(ntxIds)) {
|
||||
await this.spacedUpdate.updateNowIfNecessary();
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ function changeTitle(req) {
|
||||
const noteTitleChanged = note.title !== title;
|
||||
|
||||
if (noteTitleChanged) {
|
||||
noteService.saveNoteRevision(note);
|
||||
noteService.saveNoteRevisionIfNeeded(note);
|
||||
}
|
||||
|
||||
note.title = title;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user