diff --git a/db/migrations/0165__move_contentLength.sql b/db/migrations/0165__move_contentLength.sql new file mode 100644 index 000000000..cae0d2895 --- /dev/null +++ b/db/migrations/0165__move_contentLength.sql @@ -0,0 +1,55 @@ +CREATE TABLE IF NOT EXISTS "notes_mig" ( + `noteId` TEXT NOT NULL, + `title` TEXT NOT NULL DEFAULT "note", + `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, + `deleteId` TEXT DEFAULT NULL, + `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, isProtected, type, mime, hash, isDeleted, deleteId, isErased, dateCreated, dateModified, utcDateCreated, utcDateModified) + SELECT noteId, title, isProtected, type, mime, hash, isDeleted, deleteId, isErased, dateCreated, dateModified, utcDateCreated, utcDateModified FROM notes; + +DROP TABLE notes; +ALTER TABLE notes_mig RENAME TO notes; + +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`); + +CREATE TABLE IF NOT EXISTS "note_revisions_mig" (`noteRevisionId` TEXT NOT NULL PRIMARY KEY, + `noteId` TEXT NOT NULL, + `title` TEXT, + `isErased` INT NOT NULL DEFAULT 0, + `isProtected` INT NOT NULL DEFAULT 0, + `utcDateLastEdited` TEXT NOT NULL, + `utcDateCreated` TEXT NOT NULL, + `utcDateModified` TEXT NOT NULL, + `dateLastEdited` TEXT NOT NULL, + `dateCreated` TEXT NOT NULL, + type TEXT DEFAULT '' NOT NULL, + mime TEXT DEFAULT '' NOT NULL, + hash TEXT DEFAULT '' NOT NULL); + +INSERT INTO note_revisions_mig (noteRevisionId, noteId, title, isErased, isProtected, utcDateLastEdited, utcDateCreated, utcDateModified, dateLastEdited, dateCreated, type, mime, hash) +SELECT noteRevisionId, noteId, title, isErased, isProtected, utcDateLastEdited, utcDateCreated, utcDateModified, dateLastEdited, dateCreated, type, mime, hash FROM note_revisions; + +DROP TABLE note_revisions; +ALTER TABLE note_revisions_mig RENAME TO note_revisions; + +CREATE INDEX `IDX_note_revisions_noteId` ON `note_revisions` (`noteId`); +CREATE INDEX `IDX_note_revisions_utcDateCreated` ON `note_revisions` (`utcDateCreated`); +CREATE INDEX `IDX_note_revisions_utcDateLastEdited` ON `note_revisions` (`utcDateLastEdited`); +CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`); +CREATE INDEX `IDX_note_revisions_dateLastEdited` ON `note_revisions` (`dateLastEdited`); diff --git a/db/migrations/0166__add_dateModified_to_note_content.sql b/db/migrations/0166__add_dateModified_to_note_content.sql new file mode 100644 index 000000000..148eba7ce --- /dev/null +++ b/db/migrations/0166__add_dateModified_to_note_content.sql @@ -0,0 +1,20 @@ +CREATE TABLE IF NOT EXISTS "note_contents_mig" ( + `noteId` TEXT NOT NULL, + `content` TEXT NULL DEFAULT NULL, + `hash` TEXT DEFAULT "" NOT NULL, + `dateModified` TEXT NOT NULL, + `utcDateModified` TEXT NOT NULL, + PRIMARY KEY(`noteId`) +); + +INSERT INTO note_contents_mig (noteId, content, hash, dateModified, utcDateModified) + SELECT noteId, + content, + hash, + (SELECT dateModified FROM notes WHERE noteId = note_contents.noteId), + utcDateModified + FROM note_contents; + +DROP TABLE note_contents; + +ALTER TABLE note_contents_mig RENAME TO note_contents; diff --git a/src/entities/entity.js b/src/entities/entity.js index ff3f16603..b33fd2826 100644 --- a/src/entities/entity.js +++ b/src/entities/entity.js @@ -26,14 +26,7 @@ class Entity { const origHash = this.hash; this.hash = this.generateHash(); - - if (this.forcedChange) { - this.isChanged = true; - delete this.forcedChange; - } - else { - this.isChanged = origHash !== this.hash; - } + this.isChanged = origHash !== this.hash; } generateIdIfNecessary() { diff --git a/src/entities/note.js b/src/entities/note.js index 81b9d40d0..5daae38fa 100644 --- a/src/entities/note.js +++ b/src/entities/note.js @@ -20,7 +20,6 @@ const RELATION_DEFINITION = 'relation-definition'; * @property {string} type - one of "text", "code", "file" or "render" * @property {string} mime - MIME type, e.g. "text/html" * @property {string} title - note title - * @property {int} contentLength - length of content * @property {boolean} isProtected - true if note is protected * @property {boolean} isDeleted - true if note is deleted * @property {string|null} deleteId - ID identifying delete transaction @@ -106,6 +105,16 @@ class Note extends Entity { } } + getContentMetadata() { + return sql.getRow(` + SELECT + LENGTH(content) AS contentLength, + dateModified, + utcDateModified + FROM note_contents + WHERE noteId = ?`, [this.noteId]); + } + /** @returns {*} */ getJsonContent() { const content = this.getContent(); @@ -129,16 +138,12 @@ class Note extends Entity { content = Buffer.isBuffer(content) ? content : Buffer.from(content); } - // force updating note itself so that dateModified is represented correctly even for the content - this.forcedChange = true; - this.contentLength = content.byteLength; - this.save(); - this.content = content; const pojo = { noteId: this.noteId, content: content, + dateModified: dateUtils.localNowDateTime(), utcDateModified: dateUtils.utcNowDateTime(), hash: utils.hash(this.noteId + "|" + content.toString()) }; @@ -903,10 +908,6 @@ class Note extends Entity { this.utcDateCreated = dateUtils.utcNowDateTime(); } - if (this.contentLength === undefined) { - this.contentLength = -1; - } - super.beforeSaving(); if (this.isChanged) { diff --git a/src/entities/note_revision.js b/src/entities/note_revision.js index 5a40c83f0..32bf3c613 100644 --- a/src/entities/note_revision.js +++ b/src/entities/note_revision.js @@ -15,7 +15,6 @@ const entityChangesService = require('../services/entity_changes.js'); * @property {string} type * @property {string} mime * @property {string} title - * @property {int} contentLength * @property {boolean} isErased * @property {boolean} isProtected * @property {string} dateLastEdited @@ -29,7 +28,7 @@ const entityChangesService = require('../services/entity_changes.js'); class NoteRevision extends Entity { static get entityName() { return "note_revisions"; } static get primaryKeyName() { return "noteRevisionId"; } - static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "contentLength", "isErased", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified"]; } + static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "isErased", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified"]; } constructor(row) { super(row); @@ -101,11 +100,6 @@ class NoteRevision extends Entity { } setContent(content) { - // force updating note itself so that utcDateModified is represented correctly even for the content - this.forcedChange = true; - this.contentLength = content === null ? 0 : content.length; - this.save(); - this.content = content; const pojo = { diff --git a/src/public/app/entities/note_complement.js b/src/public/app/entities/note_complement.js index 4c75021bd..ab4049ab8 100644 --- a/src/public/app/entities/note_complement.js +++ b/src/public/app/entities/note_complement.js @@ -6,9 +6,14 @@ class NoteComplement { /** @param {string} */ this.noteId = row.noteId; - /** @param {string} */ + /** + * @param {string} - can either contain the whole content (in e.g. string notes), only part (large text notes) or nothing at all (binary notes, images) + */ this.content = row.content; + /** @param {int} */ + this.contentLength = row.contentLength; + /** @param {string} */ this.dateCreated = row.dateCreated; @@ -20,7 +25,13 @@ class NoteComplement { /** @param {string} */ this.utcDateModified = row.utcDateModified; + + /** @param {string} */ + this.combinedDateModified = row.combinedDateModified; + + /** @param {string} */ + this.combinedUtcDateModified = row.combinedUtcDateModified; } } -export default NoteComplement; \ No newline at end of file +export default NoteComplement; diff --git a/src/public/app/entities/note_short.js b/src/public/app/entities/note_short.js index 868714280..211e2a7ac 100644 --- a/src/public/app/entities/note_short.js +++ b/src/public/app/entities/note_short.js @@ -45,8 +45,6 @@ class NoteShort { this.noteId = row.noteId; /** @param {string} */ this.title = row.title; - /** @param {int} */ - this.contentLength = row.contentLength; /** @param {boolean} */ this.isProtected = !!row.isProtected; /** @param {string} one of 'text', 'code', 'file' or 'render' */ diff --git a/src/public/app/layouts/desktop_main_window_layout.js b/src/public/app/layouts/desktop_main_window_layout.js index 125994b8e..9f39417f5 100644 --- a/src/public/app/layouts/desktop_main_window_layout.js +++ b/src/public/app/layouts/desktop_main_window_layout.js @@ -110,6 +110,7 @@ export default class DesktopMainWindowLayout { .id('root-widget') .css('height', '100vh') .child(new FlexContainer('row') + .css('height', '35px') .child(new GlobalMenuWidget()) .child(new TabRowWidget()) .child(new TitleBarButtonsWidget())) @@ -130,6 +131,7 @@ export default class DesktopMainWindowLayout { .child(new FlexContainer('column').id('center-pane') .child(new FlexContainer('row').class('title-row') .cssBlock('.title-row > * { margin: 5px; }') + .css('height', '55px') .child(new NoteTitleWidget()) .child(new RunScriptButtonsWidget().hideInZenMode()) .child(new NoteTypeWidget().hideInZenMode()) diff --git a/src/public/app/services/load_results.js b/src/public/app/services/load_results.js index e62ddcd27..359dbc31c 100644 --- a/src/public/app/services/load_results.js +++ b/src/public/app/services/load_results.js @@ -120,4 +120,11 @@ export default class LoadResults { && this.contentNoteIdToSourceId.length === 0 && this.options.length === 0; } + + isEmptyForTree() { + return Object.keys(this.noteIdToSourceId).length === 0 + && this.branches.length === 0 + && this.attributes.length === 0 + && this.noteReorderings.length === 0; + } } diff --git a/src/public/app/widgets/attribute_editor.js b/src/public/app/widgets/attribute_editor.js index 53f640f94..5f076dbea 100644 --- a/src/public/app/widgets/attribute_editor.js +++ b/src/public/app/widgets/attribute_editor.js @@ -183,6 +183,7 @@ export default class AttributeEditorWidget extends TabAwareWidget { doRender() { this.$widget = $(TPL); + this.contentSized(); this.$editor = this.$widget.find('.attribute-list-editor'); this.initialized = this.initEditor(); diff --git a/src/public/app/widgets/attribute_list.js b/src/public/app/widgets/attribute_list.js index 024ed74ae..ca1e453ef 100644 --- a/src/public/app/widgets/attribute_list.js +++ b/src/public/app/widgets/attribute_list.js @@ -116,6 +116,7 @@ export default class AttributeListWidget extends TabAwareWidget { doRender() { this.$widget = $(TPL); + this.contentSized(); this.$promotedExpander = this.$widget.find('.attr-promoted-expander'); this.$allAttrWrapper = this.$widget.find('.all-attr-wrapper'); diff --git a/src/public/app/widgets/basic_widget.js b/src/public/app/widgets/basic_widget.js index 91c366a28..39e76b02b 100644 --- a/src/public/app/widgets/basic_widget.js +++ b/src/public/app/widgets/basic_widget.js @@ -25,6 +25,11 @@ class BasicWidget extends Component { return this; } + contentSized() { + this.css('contain', 'layout paint'); + return this; + } + collapsible() { this.css('min-height', '0'); return this; diff --git a/src/public/app/widgets/collapsible_widget.js b/src/public/app/widgets/collapsible_widget.js index c74ff143f..1784d4a2a 100644 --- a/src/public/app/widgets/collapsible_widget.js +++ b/src/public/app/widgets/collapsible_widget.js @@ -29,6 +29,7 @@ export default class CollapsibleWidget extends TabAwareWidget { doRender() { this.$widget = $(WIDGET_TPL); + this.contentSized(); this.$widget.find('[data-target]').attr('data-target', "#" + this.componentId); this.$bodyWrapper = this.$widget.find('.body-wrapper'); diff --git a/src/public/app/widgets/collapsible_widgets/note_info.js b/src/public/app/widgets/collapsible_widgets/note_info.js index 12a613fd8..46ac74613 100644 --- a/src/public/app/widgets/collapsible_widgets/note_info.js +++ b/src/public/app/widgets/collapsible_widgets/note_info.js @@ -64,8 +64,8 @@ export default class NoteInfoWidget extends CollapsibleWidget { .attr("title", noteComplement.dateCreated); this.$dateModified - .text(noteComplement.dateModified.substr(0, 16)) - .attr("title", noteComplement.dateCreated); + .text(noteComplement.combinedDateModified.substr(0, 16)) + .attr("title", noteComplement.combinedDateModified); this.$type.text(note.type); @@ -78,7 +78,7 @@ export default class NoteInfoWidget extends CollapsibleWidget { } entitiesReloadedEvent({loadResults}) { - if (loadResults.isNoteReloaded(this.noteId)) { + if (loadResults.isNoteReloaded(this.noteId) || loadResults.isNoteContentReloaded(this.noteId)) { this.refresh(); } } diff --git a/src/public/app/widgets/collapsible_widgets/note_revisions.js b/src/public/app/widgets/collapsible_widgets/note_revisions.js index 89e912799..3f0ac3e9e 100644 --- a/src/public/app/widgets/collapsible_widgets/note_revisions.js +++ b/src/public/app/widgets/collapsible_widgets/note_revisions.js @@ -78,4 +78,4 @@ class NoteRevisionsWidget extends CollapsibleWidget { } } -export default NoteRevisionsWidget; \ No newline at end of file +export default NoteRevisionsWidget; diff --git a/src/public/app/widgets/global_buttons.js b/src/public/app/widgets/global_buttons.js index 67b74155c..c9744fbaa 100644 --- a/src/public/app/widgets/global_buttons.js +++ b/src/public/app/widgets/global_buttons.js @@ -32,8 +32,9 @@ const WIDGET_TPL = ` class GlobalButtonsWidget extends BasicWidget { doRender() { - return this.$widget = $(WIDGET_TPL); + this.$widget = $(WIDGET_TPL); + this.contentSized(); } } -export default GlobalButtonsWidget; \ No newline at end of file +export default GlobalButtonsWidget; diff --git a/src/public/app/widgets/global_menu.js b/src/public/app/widgets/global_menu.js index bc4ea2056..febdfea59 100644 --- a/src/public/app/widgets/global_menu.js +++ b/src/public/app/widgets/global_menu.js @@ -104,6 +104,7 @@ const TPL = ` export default class GlobalMenuWidget extends BasicWidget { doRender() { this.$widget = $(TPL); + this.contentSized(); this.$widget.find(".show-about-dialog-button").on('click', () => import("../dialogs/about.js").then(d => d.showDialog())); diff --git a/src/public/app/widgets/history_navigation.js b/src/public/app/widgets/history_navigation.js index a6ab87792..099180e93 100644 --- a/src/public/app/widgets/history_navigation.js +++ b/src/public/app/widgets/history_navigation.js @@ -23,6 +23,7 @@ export default class HistoryNavigationWidget extends BasicWidget { doRender() { if (utils.isElectron()) { this.$widget = $(TPL); + this.contentSized(); const contextMenuHandler = e => { e.preventDefault(); diff --git a/src/public/app/widgets/note_actions.js b/src/public/app/widgets/note_actions.js index 92a1ab111..08c596660 100644 --- a/src/public/app/widgets/note_actions.js +++ b/src/public/app/widgets/note_actions.js @@ -93,6 +93,7 @@ const TPL = ` export default class NoteActionsWidget extends TabAwareWidget { doRender() { this.$widget = $(TPL); + this.contentSized(); this.$showSourceButton = this.$widget.find('.show-source-button'); diff --git a/src/public/app/widgets/note_paths.js b/src/public/app/widgets/note_paths.js index e99e6202d..a3ef35d80 100644 --- a/src/public/app/widgets/note_paths.js +++ b/src/public/app/widgets/note_paths.js @@ -50,6 +50,7 @@ const TPL = ` export default class NotePathsWidget extends TabAwareWidget { doRender() { this.$widget = $(TPL); + this.contentSized(); this.$currentPath = this.$widget.find('.current-path'); this.$dropdown = this.$widget.find(".dropdown"); diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.js index f5ac062f1..347351fbb 100644 --- a/src/public/app/widgets/note_tree.js +++ b/src/public/app/widgets/note_tree.js @@ -957,6 +957,10 @@ export default class NoteTreeWidget extends TabAwareWidget { } async entitiesReloadedEvent({loadResults}) { + if (loadResults.isEmptyForTree()) { + return; + } + const activeNode = this.getActiveNode(); const activeNodeFocused = activeNode && activeNode.hasFocus(); const nextNode = activeNode ? (activeNode.getNextSibling() || activeNode.getPrevSibling() || activeNode.getParent()) : null; diff --git a/src/public/app/widgets/note_type.js b/src/public/app/widgets/note_type.js index 679d6362e..0fe435119 100644 --- a/src/public/app/widgets/note_type.js +++ b/src/public/app/widgets/note_type.js @@ -34,6 +34,7 @@ const TPL = ` export default class NoteTypeWidget extends TabAwareWidget { doRender() { this.$widget = $(TPL); + this.contentSized(); this.$widget.on('show.bs.dropdown', () => this.renderDropdown()); diff --git a/src/public/app/widgets/side_pane_toggles.js b/src/public/app/widgets/side_pane_toggles.js index 5554d4d85..dc4db7714 100644 --- a/src/public/app/widgets/side_pane_toggles.js +++ b/src/public/app/widgets/side_pane_toggles.js @@ -43,6 +43,8 @@ export default class SidePaneToggles extends BasicWidget { this.$widget.find(".show-left-pane-button").on('click', () => this.toggleAndSave('left', true)); this.$widget.find(".hide-left-pane-button").on('click', () => this.toggleAndSave('left', false)); + + this.$widget.css("contain", "none"); // this widget overflows so we need to override default containment } toggleSidebar(side, show) { diff --git a/src/public/app/widgets/standard_top_widget.js b/src/public/app/widgets/standard_top_widget.js index 7a2137962..e188e446b 100644 --- a/src/public/app/widgets/standard_top_widget.js +++ b/src/public/app/widgets/standard_top_widget.js @@ -10,6 +10,7 @@ const TPL = ` display: flex; align-items: center; padding-top: 4px; + height: 35px; } .standard-top-widget button { @@ -87,4 +88,4 @@ export default class StandardTopWidget extends BasicWidget { this.$enterProtectedSessionButton.hide(); this.$leaveProtectedSessionButton.show(); } -} \ No newline at end of file +} diff --git a/src/public/app/widgets/title_bar_buttons.js b/src/public/app/widgets/title_bar_buttons.js index 3d443d7e0..f79784b00 100644 --- a/src/public/app/widgets/title_bar_buttons.js +++ b/src/public/app/widgets/title_bar_buttons.js @@ -35,6 +35,7 @@ export default class TitleBarButtonsWidget extends BasicWidget { } this.$widget = $(TPL); + this.contentSized(); const $minimizeBtn = this.$widget.find(".minimize-btn"); const $maximizeBtn = this.$widget.find(".maximize-btn"); diff --git a/src/public/app/widgets/type_widgets/file.js b/src/public/app/widgets/type_widgets/file.js index 18f6e802e..43493fbd7 100644 --- a/src/public/app/widgets/type_widgets/file.js +++ b/src/public/app/widgets/type_widgets/file.js @@ -126,11 +126,11 @@ export default class FileTypeWidget extends TypeWidget { this.$fileNoteId.text(note.noteId); this.$fileName.text(attributeMap.originalFileName || "?"); - this.$fileSize.text(note.contentLength + " bytes"); this.$fileType.text(note.mime); const noteComplement = await this.tabContext.getNoteComplement(); + this.$fileSize.text(noteComplement.contentLength + " bytes"); this.$previewContent.empty().hide(); this.$pdfPreview.attr('src', '').empty().hide(); diff --git a/src/public/app/widgets/type_widgets/image.js b/src/public/app/widgets/type_widgets/image.js index a0baf4117..5e5ffc567 100644 --- a/src/public/app/widgets/type_widgets/image.js +++ b/src/public/app/widgets/type_widgets/image.js @@ -127,8 +127,10 @@ class ImageTypeWidget extends TypeWidget { this.$widget.show(); + const noteComplement = await this.tabContext.getNoteComplement(); + this.$fileName.text(attributeMap.originalFileName || "?"); - this.$fileSize.text(note.contentLength + " bytes"); + this.$fileSize.text(noteComplement.contentLength + " bytes"); this.$fileType.text(note.mime); const imageHash = utils.randomString(10); diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index ebf1cd02b..170352578 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -635,6 +635,10 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href pointer-events: none; } +.component { + contain: strict; +} + .toast { background-color: var(--accented-background-color) !important; color: var(--main-text-color) !important; diff --git a/src/routes/api/note_revisions.js b/src/routes/api/note_revisions.js index c4b05a2b9..59af1825f 100644 --- a/src/routes/api/note_revisions.js +++ b/src/routes/api/note_revisions.js @@ -9,8 +9,12 @@ const path = require('path'); function getNoteRevisions(req) { return repository.getEntities(` - SELECT * FROM note_revisions - WHERE noteId = ? AND isErased = 0 + SELECT note_revisions.*, + LENGTH(note_revision_contents.content) AS contentLength + FROM note_revisions + JOIN note_revision_contents ON note_revisions.noteRevisionId = note_revision_contents.noteRevisionId + WHERE noteId = ? + AND isErased = 0 ORDER BY utcDateCreated DESC`, [req.params.noteId]); } diff --git a/src/routes/api/notes.js b/src/routes/api/notes.js index d3e4c50d9..4da8a3188 100644 --- a/src/routes/api/notes.js +++ b/src/routes/api/notes.js @@ -23,6 +23,11 @@ function getNote(req) { } } + const contentMetadata = note.getContentMetadata(); + + note.combinedUtcDateModified = note.utcDateModified > contentMetadata.utcDateModified ? note.utcDateModified : contentMetadata.utcDateModified; + note.combinedDateModified = note.utcDateModified > contentMetadata.utcDateModified ? note.dateModified : contentMetadata.dateModified; + return note; } diff --git a/src/services/app_info.js b/src/services/app_info.js index 6f1d62380..627cd0baf 100644 --- a/src/services/app_info.js +++ b/src/services/app_info.js @@ -4,8 +4,8 @@ const build = require('./build'); const packageJson = require('../../package'); const {TRILIUM_DATA_DIR} = require('./data_dir'); -const APP_DB_VERSION = 164; -const SYNC_VERSION = 15; +const APP_DB_VERSION = 166; +const SYNC_VERSION = 16; const CLIPPER_PROTOCOL_VERSION = "1.0"; module.exports = { diff --git a/src/services/note_cache/entities/note.js b/src/services/note_cache/entities/note.js index acad30e57..693afe7df 100644 --- a/src/services/note_cache/entities/note.js +++ b/src/services/note_cache/entities/note.js @@ -14,8 +14,6 @@ class Note { this.type = row.type; /** @param {string} */ this.mime = row.mime; - /** @param {number} */ - this.contentLength = row.contentLength; /** @param {string} */ this.dateCreated = row.dateCreated; /** @param {string} */ @@ -182,8 +180,6 @@ class Note { } this.flatTextCache = this.flatTextCache.toLowerCase(); - - console.log(this.flatTextCache); } return this.flatTextCache; diff --git a/src/services/note_cache/note_cache_loader.js b/src/services/note_cache/note_cache_loader.js index 1d0f17342..499fffb34 100644 --- a/src/services/note_cache/note_cache_loader.js +++ b/src/services/note_cache/note_cache_loader.js @@ -15,7 +15,7 @@ sqlInit.dbReady.then(() => { function load() { noteCache.reset(); - for (const row of sql.iterateRows(`SELECT noteId, title, type, mime, isProtected, dateCreated, dateModified, utcDateCreated, utcDateModified, contentLength FROM notes WHERE isDeleted = 0`, [])) { + for (const row of sql.iterateRows(`SELECT noteId, title, type, mime, isProtected, dateCreated, dateModified, utcDateCreated, utcDateModified FROM notes WHERE isDeleted = 0`, [])) { new Note(noteCache, row); } diff --git a/src/services/note_revisions.js b/src/services/note_revisions.js index e97f05c44..3772ec41c 100644 --- a/src/services/note_revisions.js +++ b/src/services/note_revisions.js @@ -34,7 +34,6 @@ function createNoteRevision(note) { noteId: note.noteId, // title and text should be decrypted now title: note.title, - contentLength: -1, // will be updated in .setContent() type: note.type, mime: note.mime, isProtected: false, // will be fixed in the protectNoteRevisions() call diff --git a/src/services/notes.js b/src/services/notes.js index e584068d5..212d75df1 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -466,7 +466,6 @@ function saveNoteRevision(note) { noteId: note.noteId, // title and text should be decrypted now title: note.title, - contentLength: -1, // will be updated in .setContent() type: note.type, mime: note.mime, isProtected: false, // will be fixed in the protectNoteRevisions() call @@ -699,7 +698,6 @@ function eraseDeletedNotes() { sql.executeMany(` UPDATE notes SET title = '[deleted]', - contentLength = 0, isProtected = 0, isErased = 1 WHERE noteId IN (???)`, noteIdsToErase); @@ -719,8 +717,7 @@ function eraseDeletedNotes() { sql.executeMany(` UPDATE note_revisions SET isErased = 1, - title = NULL, - contentLength = 0 + title = NULL WHERE isErased = 0 AND noteId IN (???)`, noteIdsToErase); sql.executeMany(` diff --git a/src/services/search/expressions/property_comparison.js b/src/services/search/expressions/property_comparison.js index 4b46d7c6f..3f37987a2 100644 --- a/src/services/search/expressions/property_comparison.js +++ b/src/services/search/expressions/property_comparison.js @@ -18,7 +18,6 @@ const PROP_MAPPING = { "datemodified": "dateModified", "utcdatecreated": "utcDateCreated", "utcdatemodified": "utcDateModified", - "contentlength": "contentLength", "parentcount": "parentCount", "childrencount": "childrenCount", "attributecount": "attributeCount", diff --git a/src/services/search/value_extractor.js b/src/services/search/value_extractor.js index ea1bb38d8..feba2cc7f 100644 --- a/src/services/search/value_extractor.js +++ b/src/services/search/value_extractor.js @@ -15,7 +15,6 @@ const PROP_MAPPING = { "datemodified": "dateModified", "utcdatecreated": "utcDateCreated", "utcdatemodified": "utcDateModified", - "contentlength": "contentLength", "parentcount": "parentCount", "childrencount": "childrenCount", "attributecount": "attributeCount", diff --git a/src/services/sql.js b/src/services/sql.js index 49b5d53f9..40926672a 100644 --- a/src/services/sql.js +++ b/src/services/sql.js @@ -93,9 +93,9 @@ function getValue(query, params = []) { return row[Object.keys(row)[0]]; } -const PARAM_LIMIT = 900; // actual limit is 999 +// smaller values can result in better performance due to better usage of statement cache +const PARAM_LIMIT = 100; -// this is to overcome 999 limit of number of query parameters function getManyRows(query, params) { let results = []; @@ -114,7 +114,11 @@ function getManyRows(query, params) { const questionMarks = curParams.map(() => ":param" + i++).join(","); const curQuery = query.replace(/\?\?\?/g, questionMarks); - const subResults = dbConnection.prepare(curQuery).all(curParamsObj); + const statement = curParams.length === PARAM_LIMIT + ? stmt(curQuery) + : dbConnection.prepare(curQuery); + + const subResults = statement.all(curParamsObj); results = results.concat(subResults); } diff --git a/src/services/tree.js b/src/services/tree.js index ccf70ea29..582517c36 100644 --- a/src/services/tree.js +++ b/src/services/tree.js @@ -12,7 +12,6 @@ function getNotes(noteIds) { SELECT noteId, title, - contentLength, isProtected, type, mime,