mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
note revision save also saves attachments
This commit is contained in:
parent
6cf0fe0b73
commit
34ecd77bd4
@ -119,7 +119,14 @@ class AbstractBeccaEntity {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @protected */
|
/**
|
||||||
|
* Hot entities keep stable blobId which is continuously updated and is not shared with other entities.
|
||||||
|
* Cold entities can still update its blob, but the blobId will change (and new blob will be created).
|
||||||
|
* Functionally this is the same, it's an optimization to avoid creating a new blob every second with auto saved
|
||||||
|
* text notes.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
_isHot() {
|
_isHot() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -128,6 +135,7 @@ class AbstractBeccaEntity {
|
|||||||
_setContent(content, opts = {}) {
|
_setContent(content, opts = {}) {
|
||||||
// client code asks to save entity even if blobId didn't change (something else was changed)
|
// client code asks to save entity even if blobId didn't change (something else was changed)
|
||||||
opts.forceSave = !!opts.forceSave;
|
opts.forceSave = !!opts.forceSave;
|
||||||
|
opts.forceCold = !!opts.forceCold;
|
||||||
|
|
||||||
if (content === null || content === undefined) {
|
if (content === null || content === undefined) {
|
||||||
throw new Error(`Cannot set null content to ${this.constructor.primaryKeyName} '${this[this.constructor.primaryKeyName]}'`);
|
throw new Error(`Cannot set null content to ${this.constructor.primaryKeyName} '${this[this.constructor.primaryKeyName]}'`);
|
||||||
@ -150,7 +158,7 @@ class AbstractBeccaEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sql.transactional(() => {
|
sql.transactional(() => {
|
||||||
let newBlobId = this._saveBlob(content);
|
let newBlobId = this._saveBlob(content, opts);
|
||||||
|
|
||||||
if (newBlobId !== this.blobId || opts.forceSave) {
|
if (newBlobId !== this.blobId || opts.forceSave) {
|
||||||
this.blobId = newBlobId;
|
this.blobId = newBlobId;
|
||||||
@ -160,11 +168,11 @@ class AbstractBeccaEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @protected */
|
/** @protected */
|
||||||
_saveBlob(content) {
|
_saveBlob(content, opts) {
|
||||||
let newBlobId;
|
let newBlobId;
|
||||||
let blobNeedsInsert;
|
let blobNeedsInsert;
|
||||||
|
|
||||||
if (this._isHot()) {
|
if (this._isHot() && !opts.forceCold) {
|
||||||
newBlobId = this.blobId || utils.randomBlobId();
|
newBlobId = this.blobId || utils.randomBlobId();
|
||||||
blobNeedsInsert = true;
|
blobNeedsInsert = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -55,6 +55,19 @@ class BAttachment extends AbstractBeccaEntity {
|
|||||||
this.utcDateScheduledForDeletionSince = row.utcDateScheduledForDeletionSince;
|
this.utcDateScheduledForDeletionSince = row.utcDateScheduledForDeletionSince;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {BAttachment} */
|
||||||
|
copy() {
|
||||||
|
return new BAttachment({
|
||||||
|
parentId: this.parentId,
|
||||||
|
role: this.role,
|
||||||
|
mime: this.mime,
|
||||||
|
title: this.title,
|
||||||
|
blobId: this.blobId,
|
||||||
|
isProtected: this.isProtected,
|
||||||
|
utcDateScheduledForDeletionSince: this.utcDateScheduledForDeletionSince
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getNote() {
|
getNote() {
|
||||||
return becca.notes[this.parentId];
|
return becca.notes[this.parentId];
|
||||||
}
|
}
|
||||||
@ -73,6 +86,7 @@ class BAttachment extends AbstractBeccaEntity {
|
|||||||
* @param content
|
* @param content
|
||||||
* @param {object} [opts]
|
* @param {object} [opts]
|
||||||
* @param {object} [opts.forceSave=false] - will also save this BAttachment entity
|
* @param {object} [opts.forceSave=false] - will also save this BAttachment entity
|
||||||
|
* @param {object} [opts.forceCold=false] - blob has to be saved as cold
|
||||||
*/
|
*/
|
||||||
setContent(content, opts) {
|
setContent(content, opts) {
|
||||||
this._setContent(content, opts);
|
this._setContent(content, opts);
|
||||||
|
@ -241,6 +241,7 @@ class BNote extends AbstractBeccaEntity {
|
|||||||
* @param content
|
* @param content
|
||||||
* @param {object} [opts]
|
* @param {object} [opts]
|
||||||
* @param {object} [opts.forceSave=false] - will also save this BNote entity
|
* @param {object} [opts.forceSave=false] - will also save this BNote entity
|
||||||
|
* @param {object} [opts.forceCold=false] - blob has to be saved as cold
|
||||||
*/
|
*/
|
||||||
setContent(content, opts) {
|
setContent(content, opts) {
|
||||||
this._setContent(content, opts);
|
this._setContent(content, opts);
|
||||||
@ -1521,35 +1522,43 @@ class BNote extends AbstractBeccaEntity {
|
|||||||
* @returns {BNoteRevision|null}
|
* @returns {BNoteRevision|null}
|
||||||
*/
|
*/
|
||||||
saveNoteRevision() {
|
saveNoteRevision() {
|
||||||
const content = this.getContent();
|
return sql.transactional(() => {
|
||||||
|
const content = this.getContent();
|
||||||
|
const contentMetadata = this.getContentMetadata();
|
||||||
|
|
||||||
if (!content || (Buffer.isBuffer(content) && content.byteLength === 0)) {
|
const noteRevision = new BNoteRevision({
|
||||||
return null;
|
noteId: this.noteId,
|
||||||
}
|
// title and text should be decrypted now
|
||||||
|
title: this.title,
|
||||||
|
type: this.type,
|
||||||
|
mime: this.mime,
|
||||||
|
isProtected: this.isProtected,
|
||||||
|
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()
|
||||||
|
}, true);
|
||||||
|
|
||||||
const contentMetadata = this.getContentMetadata();
|
noteRevision.setContent(content, { forceSave: true });
|
||||||
|
|
||||||
const noteRevision = new BNoteRevision({
|
for (const noteAttachment of this.getAttachments()) {
|
||||||
noteId: this.noteId,
|
const content = noteAttachment.getContent();
|
||||||
// title and text should be decrypted now
|
|
||||||
title: this.title,
|
|
||||||
type: this.type,
|
|
||||||
mime: this.mime,
|
|
||||||
isProtected: this.isProtected,
|
|
||||||
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()
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
noteRevision.setContent(content, { forceSave: true });
|
const revisionAttachment = noteAttachment.copy();
|
||||||
|
revisionAttachment.parentId = noteRevision.noteRevisionId;
|
||||||
|
revisionAttachment.setContent(content, {
|
||||||
|
forceSave: true,
|
||||||
|
forceCold: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return noteRevision;
|
return noteRevision;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +48,7 @@ export default class AttachmentDetailTypeWidget extends TypeWidget {
|
|||||||
async entitiesReloadedEvent({loadResults}) {
|
async entitiesReloadedEvent({loadResults}) {
|
||||||
const attachmentChange = loadResults.getAttachments().find(att => att.attachmentId === this.attachment.attachmentId);
|
const attachmentChange = loadResults.getAttachments().find(att => att.attachmentId === this.attachment.attachmentId);
|
||||||
|
|
||||||
if (attachmentChange.isDeleted) {
|
if (attachmentChange?.isDeleted) {
|
||||||
this.refresh(); // all other updates are handled within AttachmentDetailWidget
|
this.refresh(); // all other updates are handled within AttachmentDetailWidget
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user