Compare commits

...

10 Commits

15 changed files with 54 additions and 18 deletions

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "trilium", "name": "trilium",
"version": "0.46.4-beta", "version": "0.46.5",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@@ -2,7 +2,7 @@
"name": "trilium", "name": "trilium",
"productName": "Trilium Notes", "productName": "Trilium Notes",
"description": "Trilium Notes", "description": "Trilium Notes",
"version": "0.46.5", "version": "0.46.6",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"main": "electron.js", "main": "electron.js",
"bin": { "bin": {
@@ -14,7 +14,7 @@
}, },
"scripts": { "scripts": {
"start-server": "cross-env TRILIUM_ENV=dev node ./src/www", "start-server": "cross-env TRILIUM_ENV=dev node ./src/www",
"start-electron": "cross-env TRILIUM_ENV=dev electron .", "start-electron": "cross-env TRILIUM_ENV=dev electron --inspect=5858 .",
"build-backend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/entities/*.js src/services/backend_script_api.js", "build-backend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/entities/*.js src/services/backend_script_api.js",
"build-frontend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/collapsible_widget.js", "build-frontend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/collapsible_widget.js",
"build-docs": "npm run build-backend-docs && npm run build-frontend-docs", "build-docs": "npm run build-backend-docs && npm run build-frontend-docs",

View File

@@ -156,14 +156,14 @@ class Note extends Entity {
sql.upsert("note_contents", "noteId", pojo); sql.upsert("note_contents", "noteId", pojo);
const hash = utils.hash(this.noteId + "|" + content.toString()); const hash = utils.hash(this.noteId + "|" + pojo.content.toString());
entityChangesService.addEntityChange({ entityChangesService.addEntityChange({
entityName: 'note_contents', entityName: 'note_contents',
entityId: this.noteId, entityId: this.noteId,
hash: hash, hash: hash,
isErased: false, isErased: false,
utcDateChanged: this.getUtcDateChanged() utcDateChanged: pojo.utcDateModified
}, null); }, null);
} }

View File

@@ -83,6 +83,9 @@ export default class MobileLayout {
.child(new NoteTitleWidget()) .child(new NoteTitleWidget())
.child(new CloseDetailButtonWidget())) .child(new CloseDetailButtonWidget()))
.child(new NoteDetailWidget() .child(new NoteDetailWidget()
.css('padding', '5px 20px 10px 0'))); .css('padding', '5px 20px 10px 0')
.css('overflow', 'auto')
.css('height', '100%')
));
} }
} }

View File

@@ -36,7 +36,7 @@ export default class NoteTitleWidget extends TabAwareWidget {
protectedSessionHolder.touchProtectedSessionIfNecessary(this.note); protectedSessionHolder.touchProtectedSessionIfNecessary(this.note);
await server.put(`notes/${this.noteId}/change-title`, {title}); await server.put(`notes/${this.noteId}/change-title`, {title}, this.componentId);
}); });
appContext.addBeforeUnloadListener(this); appContext.addBeforeUnloadListener(this);

View File

@@ -176,6 +176,15 @@ const TPL = `
title="Images which are shown in the parent text note will not be displayed in the tree"></span> title="Images which are shown in the parent text note will not be displayed in the tree"></span>
</label> </label>
</div> </div>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input auto-collapse-note-tree" type="checkbox" value="">
Automatically collapse notes
<span class="bx bx-info-circle"
title="Notes will be collapsed after period of inactivity to declutter the tree."></span>
</label>
</div>
<br/> <br/>
@@ -235,6 +244,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
this.$treeSettingsPopup = this.$widget.find('.tree-settings-popup'); this.$treeSettingsPopup = this.$widget.find('.tree-settings-popup');
this.$hideArchivedNotesCheckbox = this.$treeSettingsPopup.find('.hide-archived-notes'); this.$hideArchivedNotesCheckbox = this.$treeSettingsPopup.find('.hide-archived-notes');
this.$hideIncludedImages = this.$treeSettingsPopup.find('.hide-included-images'); this.$hideIncludedImages = this.$treeSettingsPopup.find('.hide-included-images');
this.$autoCollapseNoteTree = this.$treeSettingsPopup.find('.auto-collapse-note-tree');
this.$treeSettingsButton = this.$widget.find('.tree-settings-button'); this.$treeSettingsButton = this.$widget.find('.tree-settings-button');
this.$treeSettingsButton.on("click", e => { this.$treeSettingsButton.on("click", e => {
@@ -245,6 +255,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
this.$hideArchivedNotesCheckbox.prop("checked", this.hideArchivedNotes); this.$hideArchivedNotesCheckbox.prop("checked", this.hideArchivedNotes);
this.$hideIncludedImages.prop("checked", this.hideIncludedImages); this.$hideIncludedImages.prop("checked", this.hideIncludedImages);
this.$autoCollapseNoteTree.prop("checked", this.autoCollapseNoteTree);
let top = this.$treeSettingsButton[0].offsetTop; let top = this.$treeSettingsButton[0].offsetTop;
let left = this.$treeSettingsButton[0].offsetLeft; let left = this.$treeSettingsButton[0].offsetLeft;
@@ -272,6 +283,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
this.$saveTreeSettingsButton.on('click', async () => { this.$saveTreeSettingsButton.on('click', async () => {
await this.setHideArchivedNotes(this.$hideArchivedNotesCheckbox.prop("checked")); await this.setHideArchivedNotes(this.$hideArchivedNotesCheckbox.prop("checked"));
await this.setHideIncludedImages(this.$hideIncludedImages.prop("checked")); await this.setHideIncludedImages(this.$hideIncludedImages.prop("checked"));
await this.setAutoCollapseNoteTree(this.$autoCollapseNoteTree.prop("checked"));
this.$treeSettingsPopup.hide(); this.$treeSettingsPopup.hide();
@@ -327,6 +339,14 @@ export default class NoteTreeWidget extends TabAwareWidget {
await options.save("hideIncludedImages_" + this.treeName, val.toString()); await options.save("hideIncludedImages_" + this.treeName, val.toString());
} }
get autoCollapseNoteTree() {
return options.is("autoCollapseNoteTree");
}
async setAutoCollapseNoteTree(val) {
await options.save("autoCollapseNoteTree", val.toString());
}
initFancyTree() { initFancyTree() {
const treeData = [this.prepareRootNode()]; const treeData = [this.prepareRootNode()];
@@ -797,8 +817,10 @@ export default class NoteTreeWidget extends TabAwareWidget {
const node = await this.expandToNote(activeContext.notePath); const node = await this.expandToNote(activeContext.notePath);
await node.makeVisible({scrollIntoView: true}); if (node) {
node.setActive(true, {noEvents: true, noFocus: false}); await node.makeVisible({scrollIntoView: true});
node.setActive(true, {noEvents: true, noFocus: false});
}
} }
} }
@@ -851,7 +873,11 @@ export default class NoteTreeWidget extends TabAwareWidget {
// these are real notes with real notePath, user can display them in a detail // these are real notes with real notePath, user can display them in a detail
// but they don't have a node in the tree // but they don't have a node in the tree
ws.logError(`Can't find node for child node of noteId=${childNoteId} for parent of noteId=${parentNode.data.noteId} and hoistedNoteId=${hoistedNoteService.getHoistedNoteId()}, requested path is ${notePath}`); const childNote = await treeCache.getNote(childNoteId);
if (!childNote || childNote.type !== 'image') {
ws.logError(`Can't find node for child node of noteId=${childNoteId} for parent of noteId=${parentNode.data.noteId} and hoistedNoteId=${hoistedNoteService.getHoistedNoteId()}, requested path is ${notePath}`);
}
} }
return; return;
@@ -955,6 +981,10 @@ export default class NoteTreeWidget extends TabAwareWidget {
} }
this.autoCollapseTimeoutId = setTimeout(() => { this.autoCollapseTimeoutId = setTimeout(() => {
if (!this.autoCollapseNoteTree) {
return;
}
/* /*
* We're collapsing notes after period of inactivity to "cleanup" the tree - users rarely * We're collapsing notes after period of inactivity to "cleanup" the tree - users rarely
* collapse the notes and the tree becomes unusuably large. * collapse the notes and the tree becomes unusuably large.

View File

@@ -5,6 +5,7 @@ const TPL = `
<style> <style>
.note-detail-read-only-code { .note-detail-read-only-code {
position: relative; position: relative;
min-height: 50px;
} }
.note-detail-read-only-code-content { .note-detail-read-only-code-content {

View File

@@ -25,6 +25,7 @@ const TPL = `
padding-top: 10px; padding-top: 10px;
font-family: var(--detail-text-font-family); font-family: var(--detail-text-font-family);
position: relative; position: relative;
min-height: 50px;
} }
.note-detail-readonly-text p:first-child, .note-detail-readonly-text::before { .note-detail-readonly-text p:first-child, .note-detail-readonly-text::before {

View File

@@ -5,6 +5,7 @@ const noteCacheService = require('../../services/note_cache/note_cache_service')
const protectedSessionService = require('../../services/protected_session'); const protectedSessionService = require('../../services/protected_session');
const noteRevisionService = require('../../services/note_revisions'); const noteRevisionService = require('../../services/note_revisions');
const utils = require('../../services/utils'); const utils = require('../../services/utils');
const sql = require('../../services/sql');
const path = require('path'); const path = require('path');
function getNoteRevisions(req) { function getNoteRevisions(req) {

View File

@@ -41,7 +41,8 @@ const ALLOWED_OPTIONS = new Set([
'attributeListExpanded', 'attributeListExpanded',
'promotedAttributesExpanded', 'promotedAttributesExpanded',
'similarNotesExpanded', 'similarNotesExpanded',
'headingStyle' 'headingStyle',
'autoCollapseNoteTree'
]); ]);
function getOptions() { function getOptions() {

View File

@@ -1 +1 @@
module.exports = { buildDate:"2021-03-14T22:56:27+01:00", buildRevision: "6c8d20288df302f3a415bd1bdcace98bf29d4bf6" }; module.exports = { buildDate:"2021-03-23T23:57:48+01:00", buildRevision: "1862acd1ff9261536ebc7118d35bbbd8449ba94d" };

View File

@@ -405,7 +405,7 @@ class Note {
return 0; return 0;
} }
let minDistance = 999_999; let minDistance = 999999;
for (const parent of this.parents) { for (const parent of this.parents) {
minDistance = Math.min(minDistance, parent.getDistanceToAncestor(ancestorNoteId) + 1); minDistance = Math.min(minDistance, parent.getDistanceToAncestor(ancestorNoteId) + 1);

View File

@@ -233,7 +233,7 @@ async function findSimilarNotes(noteId) {
const baseNote = noteCache.notes[noteId]; const baseNote = noteCache.notes[noteId];
if (!baseNote) { if (!baseNote || !baseNote.utcDateCreated) {
return []; return [];
} }

View File

@@ -86,6 +86,7 @@ const defaultOptions = [
{ name: 'similarNotesExpanded', value: 'true', isSynced: true }, { name: 'similarNotesExpanded', value: 'true', isSynced: true },
{ name: 'debugModeEnabled', value: 'false', isSynced: false }, { name: 'debugModeEnabled', value: 'false', isSynced: false },
{ name: 'headingStyle', value: 'markdown', isSynced: true }, { name: 'headingStyle', value: 'markdown', isSynced: true },
{ name: 'autoCollapseNoteTree', value: 'true', isSynced: true },
]; ];
function initStartupOptions() { function initStartupOptions() {

View File

@@ -26,9 +26,7 @@ function updateEntity(entityChange, entity, sourceId) {
? updateNoteReordering(entityChange, entity, sourceId) ? updateNoteReordering(entityChange, entity, sourceId)
: updateNormalEntity(entityChange, entity, sourceId); : updateNormalEntity(entityChange, entity, sourceId);
// currently making exception for protected notes and note revisions because here if (updated && !entityChange.isErased) {
// the title and content are not available decrypted as listeners would expect
if (updated && !entity.isProtected && !entityChange.isErased) {
eventService.emit(eventService.ENTITY_SYNCED, { eventService.emit(eventService.ENTITY_SYNCED, {
entityName: entityChange.entityName, entityName: entityChange.entityName,
entity entity
@@ -44,7 +42,7 @@ function updateNormalEntity(remoteEntityChange, entity, sourceId) {
if (localEntityChange && !localEntityChange.isErased && remoteEntityChange.isErased) { if (localEntityChange && !localEntityChange.isErased && remoteEntityChange.isErased) {
sql.transactional(() => { sql.transactional(() => {
const primaryKey = entityConstructor.getEntityFromEntityName(entityName).primaryKeyName; const primaryKey = entityConstructor.getEntityFromEntityName(remoteEntityChange.entityName).primaryKeyName;
sql.execute(`DELETE FROM ${remoteEntityChange.entityName} WHERE ${primaryKey} = ?`, remoteEntityChange.entityId); sql.execute(`DELETE FROM ${remoteEntityChange.entityName} WHERE ${primaryKey} = ?`, remoteEntityChange.entityId);