added contentLength to note entity

This commit is contained in:
zadam 2019-11-09 09:36:08 +01:00
parent 5aa5ec3af1
commit 7c7beb5502
19 changed files with 94 additions and 73 deletions

View File

@ -0,0 +1,34 @@
CREATE TABLE IF NOT EXISTS "notes_mig" (
`noteId` TEXT NOT NULL,
`title` TEXT NOT NULL DEFAULT "note",
`contentLength` INT NOT NULL,
`isProtected` INT NOT NULL DEFAULT 0,
`type` TEXT NOT NULL DEFAULT 'text',
`mime` TEXT NOT NULL DEFAULT 'text/html',
`hash` TEXT DEFAULT "" NOT NULL,
`isDeleted` INT NOT NULL DEFAULT 0,
`isErased` INT NOT NULL DEFAULT 0,
`dateCreated` TEXT NOT NULL,
`dateModified` TEXT NOT NULL,
`utcDateCreated` TEXT NOT NULL,
`utcDateModified` TEXT NOT NULL,
PRIMARY KEY(`noteId`));
INSERT INTO notes_mig (noteId, title, contentLength, isProtected, type, mime, hash, isDeleted, isErased, dateCreated, dateModified, utcDateCreated, utcDateModified)
SELECT noteId, title, -1, isProtected, type, mime, hash, isDeleted, isErased, dateCreated, dateModified, utcDateCreated, utcDateModified FROM notes;
DROP TABLE notes;
ALTER TABLE notes_mig RENAME TO notes;
UPDATE notes SET contentLength = (SELECT COALESCE(LENGTH(content), 0) FROM note_contents WHERE note_contents.noteId = notes.noteId);
CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`);
CREATE INDEX `IDX_notes_title` ON `notes` (`title`);
CREATE INDEX `IDX_notes_type` ON `notes` (`type`);
CREATE INDEX `IDX_notes_dateCreated` ON `notes` (`dateCreated`);
CREATE INDEX `IDX_notes_dateModified` ON `notes` (`dateModified`);
CREATE INDEX `IDX_notes_utcDateModified` ON `notes` (`utcDateModified`);
CREATE INDEX `IDX_notes_utcDateCreated` ON `notes` (`utcDateCreated`);
-- should be OK since sync protocol changes so all instances must upgrade
UPDATE attributes SET isDeleted = 1 WHERE name = 'fileSize';

View File

@ -6,10 +6,10 @@ const dateUtils = require('../services/date_utils');
/** /**
* ApiToken is an entity representing token used to authenticate against Trilium API from client applications. Currently used only by Trilium Sender. * ApiToken is an entity representing token used to authenticate against Trilium API from client applications. Currently used only by Trilium Sender.
* *
* @param {string} apiTokenId - primary key * @property {string} apiTokenId - primary key
* @param {string} token * @property {string} token
* @param {boolean} isDeleted - true if API token is deleted * @property {boolean} isDeleted - true if API token is deleted
* @param {string} utcDateCreated * @property {string} utcDateCreated
* *
* @extends Entity * @extends Entity
*/ */

View File

@ -8,16 +8,16 @@ const sql = require('../services/sql');
/** /**
* Attribute is key value pair owned by a note. * Attribute is key value pair owned by a note.
* *
* @param {string} attributeId * @property {string} attributeId
* @param {string} noteId * @property {string} noteId
* @param {string} type * @property {string} type
* @param {string} name * @property {string} name
* @param {string} value * @property {string} value
* @param {int} position * @property {int} position
* @param {boolean} isInheritable * @property {boolean} isInheritable
* @param {boolean} isDeleted * @property {boolean} isDeleted
* @param {string} utcDateCreated * @property {string} utcDateCreated
* @param {string} utcDateModified * @property {string} utcDateModified
* *
* @extends Entity * @extends Entity
*/ */

View File

@ -9,15 +9,15 @@ const sql = require('../services/sql');
* Branch represents note's placement in the tree - it's essentially pair of noteId and parentNoteId. * Branch represents note's placement in the tree - it's essentially pair of noteId and parentNoteId.
* Each note can have multiple (at least one) branches, meaning it can be placed into multiple places in the tree. * Each note can have multiple (at least one) branches, meaning it can be placed into multiple places in the tree.
* *
* @param {string} branchId - primary key * @property {string} branchId - primary key
* @param {string} noteId * @property {string} noteId
* @param {string} parentNoteId * @property {string} parentNoteId
* @param {int} notePosition * @property {int} notePosition
* @param {string} prefix * @property {string} prefix
* @param {boolean} isExpanded * @property {boolean} isExpanded
* @param {boolean} isDeleted * @property {boolean} isDeleted
* @param {string} utcDateModified * @property {string} utcDateModified
* @param {string} utcDateCreated * @property {string} utcDateCreated
* *
* @extends Entity * @extends Entity
*/ */

View File

@ -21,6 +21,7 @@ const RELATION_DEFINITION = 'relation-definition';
* @property {string} type - one of "text", "code", "file" or "render" * @property {string} type - one of "text", "code", "file" or "render"
* @property {string} mime - MIME type, e.g. "text/html" * @property {string} mime - MIME type, e.g. "text/html"
* @property {string} title - note title * @property {string} title - note title
* @property {int} contentLength - length of content
* @property {boolean} isProtected - true if note is protected * @property {boolean} isProtected - true if note is protected
* @property {boolean} isDeleted - true if note is deleted * @property {boolean} isDeleted - true if note is deleted
* @property {boolean} isErased - true if note's content is erased after it has been deleted * @property {boolean} isErased - true if note's content is erased after it has been deleted
@ -115,6 +116,7 @@ class Note extends Entity {
async setContent(content) { async setContent(content) {
// force updating note itself so that dateModified is represented correctly even for the content // force updating note itself so that dateModified is represented correctly even for the content
this.forcedChange = true; this.forcedChange = true;
this.contentLength = content.length;
await this.save(); await this.save();
this.content = content; this.content = content;
@ -739,6 +741,10 @@ class Note extends Entity {
this.utcDateCreated = dateUtils.utcNowDateTime(); this.utcDateCreated = dateUtils.utcNowDateTime();
} }
if (this.contentLength === undefined) {
this.contentLength = -1;
}
super.beforeSaving(); super.beforeSaving();
if (this.isChanged) { if (this.isChanged) {

View File

@ -11,17 +11,18 @@ const syncTableService = require('../services/sync_table');
/** /**
* NoteRevision represents snapshot of note's title and content at some point in the past. It's used for seamless note versioning. * NoteRevision represents snapshot of note's title and content at some point in the past. It's used for seamless note versioning.
* *
* @param {string} noteRevisionId * @property {string} noteRevisionId
* @param {string} noteId * @property {string} noteId
* @param {string} type * @property {string} type
* @param {string} mime * @property {string} mime
* @param {string} title * @property {string} title
* @param {string} isProtected * @property {int} contentLength - length of content
* @param {string} dateLastEdited * @property {string} isProtected
* @param {string} dateCreated * @property {string} dateLastEdited
* @param {string} utcDateLastEdited * @property {string} dateCreated
* @param {string} utcDateCreated * @property {string} utcDateLastEdited
* @param {string} utcDateModified * @property {string} utcDateCreated
* @property {string} utcDateModified
* *
* @extends Entity * @extends Entity
*/ */

View File

@ -6,11 +6,11 @@ const dateUtils = require('../services/date_utils');
/** /**
* Option represents name-value pair, either directly configurable by the user or some system property. * Option represents name-value pair, either directly configurable by the user or some system property.
* *
* @param {string} name * @property {string} name
* @param {string} value * @property {string} value
* @param {boolean} isSynced * @property {boolean} isSynced
* @param {string} utcDateModified * @property {string} utcDateModified
* @param {string} utcDateCreated * @property {string} utcDateCreated
* *
* @extends Entity * @extends Entity
*/ */

View File

@ -6,10 +6,10 @@ const dateUtils = require('../services/date_utils');
/** /**
* RecentNote represents recently visited note. * RecentNote represents recently visited note.
* *
* @param {string} noteId * @property {string} noteId
* @param {string} notePath * @property {string} notePath
* @param {boolean} isDeleted * @property {boolean} isDeleted
* @param {string} utcDateModified * @property {string} utcDateModified
* *
* @extends Entity * @extends Entity
*/ */

View File

@ -21,6 +21,8 @@ class NoteShort {
this.noteId = row.noteId; this.noteId = row.noteId;
/** @param {string} */ /** @param {string} */
this.title = row.title; this.title = row.title;
/** @param {int} */
this.contentLength = row.contentLength;
/** @param {boolean} */ /** @param {boolean} */
this.isProtected = row.isProtected; this.isProtected = row.isProtected;
/** @param {string} one of 'text', 'code', 'file' or 'render' */ /** @param {string} one of 'text', 'code', 'file' or 'render' */

View File

@ -39,7 +39,7 @@ class NoteDetailFile {
this.$fileNoteId.text(this.ctx.note.noteId); this.$fileNoteId.text(this.ctx.note.noteId);
this.$fileName.text(attributeMap.originalFileName || "?"); this.$fileName.text(attributeMap.originalFileName || "?");
this.$fileSize.text((attributeMap.fileSize || "?") + " bytes"); this.$fileSize.text(this.ctx.note.contentLength + " bytes");
this.$fileType.text(this.ctx.note.mime); this.$fileType.text(this.ctx.note.mime);
if (this.ctx.note.content) { if (this.ctx.note.content) {

View File

@ -81,7 +81,7 @@ class NoteDetailImage {
this.$component.show(); this.$component.show();
this.$fileName.text(attributeMap.originalFileName || "?"); this.$fileName.text(attributeMap.originalFileName || "?");
this.$fileSize.text((attributeMap.fileSize || "?") + " bytes"); this.$fileSize.text(this.ctx.note.contentLength + " bytes");
this.$fileType.text(this.ctx.note.mime); this.$fileType.text(this.ctx.note.mime);
const imageHash = this.ctx.note.utcDateModified.replace(" ", "_"); const imageHash = this.ctx.note.utcDateModified.replace(" ", "_");

View File

@ -23,10 +23,7 @@ async function uploadFile(req) {
isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(),
type: mime.startsWith("image/") ? 'image' : 'file', type: mime.startsWith("image/") ? 'image' : 'file',
mime: file.mimetype, mime: file.mimetype,
attributes: [ attributes: [{ type: "label", name: "originalFileName", value: originalName }]
{ type: "label", name: "originalFileName", value: originalName },
{ type: "label", name: "fileSize", value: size }
]
}); });
return { return {

View File

@ -4,7 +4,7 @@ const build = require('./build');
const packageJson = require('../../package'); const packageJson = require('../../package');
const {TRILIUM_DATA_DIR} = require('./data_dir'); const {TRILIUM_DATA_DIR} = require('./data_dir');
const APP_DB_VERSION = 151; const APP_DB_VERSION = 152;
const SYNC_VERSION = 11; const SYNC_VERSION = 11;
const CLIPPER_PROTOCOL_VERSION = "1.0"; const CLIPPER_PROTOCOL_VERSION = "1.0";

View File

@ -60,7 +60,6 @@ async function updateImage(noteId, uploadBuffer, originalName) {
await note.setContent(buffer); await note.setContent(buffer);
await note.setLabel('originalFileName', originalName); await note.setLabel('originalFileName', originalName);
await note.setLabel('fileSize', buffer.byteLength);
await noteService.protectNoteRevisions(note); await noteService.protectNoteRevisions(note);
} }
@ -77,10 +76,7 @@ async function saveImage(parentNoteId, uploadBuffer, originalName, shrinkImageSw
type: 'image', type: 'image',
isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(),
mime: 'image/' + imageFormat.ext.toLowerCase(), mime: 'image/' + imageFormat.ext.toLowerCase(),
attributes: [ attributes: [{ type: 'label', name: 'originalFileName', value: originalName }]
{ type: 'label', name: 'originalFileName', value: originalName },
{ type: 'label', name: 'fileSize', value: buffer.byteLength }
]
}); });
return { return {

View File

@ -139,12 +139,6 @@ async function importEnex(taskContext, file, parentNote) {
text = text.replace(/\s/g, ''); text = text.replace(/\s/g, '');
resource.content = utils.fromBase64(text); resource.content = utils.fromBase64(text);
resource.attributes.push({
type: 'label',
name: 'fileSize',
value: resource.content.length
});
} }
else if (currentTag === 'mime') { else if (currentTag === 'mime') {
resource.mime = text.toLowerCase(); resource.mime = text.toLowerCase();

View File

@ -48,10 +48,7 @@ async function importFile(taskContext, file, parentNote) {
isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(),
type: 'file', type: 'file',
mime: mimeService.getMime(originalName) || file.mimetype, mime: mimeService.getMime(originalName) || file.mimetype,
attributes: [ attributes: [{ type: "label", name: "originalFileName", value: originalName }]
{ type: "label", name: "originalFileName", value: originalName },
{ type: "label", name: "fileSize", value: size }
]
}); });
taskContext.increaseProgressCount(); taskContext.increaseProgressCount();

View File

@ -352,13 +352,6 @@ async function importTar(taskContext, fileBuffer, importRootNote) {
name: 'originalFileName', name: 'originalFileName',
value: path.basename(filePath) value: path.basename(filePath)
}); });
attributes.push({
noteId,
type: 'label',
name: 'fileSize',
value: content.byteLength
});
} }
} }

View File

@ -465,6 +465,7 @@ async function eraseDeletedNotes() {
// it's better to not use repository for this because it will complain about saving protected notes // it's better to not use repository for this because it will complain about saving protected notes
// out of protected session // out of protected session
// setting contentLength to zero would serve no benefit and it leaves potentially useful trail
await sql.executeMany(` await sql.executeMany(`
UPDATE notes UPDATE notes
SET isErased = 1, SET isErased = 1,