From 0054a32dc7e6a8ac0c4417d01479ef7189a80967 Mon Sep 17 00:00:00 2001 From: zadam Date: Sat, 1 Feb 2020 22:29:32 +0100 Subject: [PATCH] treecache now manages reloading when starting protected session --- src/public/javascripts/mobile.js | 4 +- .../javascripts/services/app_context.js | 7 ++- .../javascripts/services/spaced_update.js | 2 +- .../javascripts/services/tab_context.js | 10 ++--- src/public/javascripts/services/tree.js | 10 +---- .../javascripts/services/tree_builder.js | 2 + src/public/javascripts/services/tree_cache.js | 16 +++---- src/public/javascripts/widgets/note_detail.js | 4 -- src/public/javascripts/widgets/note_title.js | 5 +-- src/public/javascripts/widgets/note_tree.js | 12 ++--- .../javascripts/widgets/tab_aware_widget.js | 4 ++ src/public/javascripts/widgets/tab_row.js | 14 +++--- .../javascripts/widgets/type_widgets/code.js | 4 +- .../widgets/type_widgets/relation_map.js | 4 -- .../javascripts/widgets/type_widgets/text.js | 4 +- src/routes/api/branches.js | 44 +++++++++---------- src/services/ws.js | 5 +++ 17 files changed, 76 insertions(+), 75 deletions(-) diff --git a/src/public/javascripts/mobile.js b/src/public/javascripts/mobile.js index 44e5eac44..636d503a4 100644 --- a/src/public/javascripts/mobile.js +++ b/src/public/javascripts/mobile.js @@ -1,11 +1,9 @@ import treeService from "./services/tree.js"; -import noteDetailService from "./services/note_detail.js"; import treeCache from "./services/tree_cache.js"; import treeBuilder from "./services/tree_builder.js"; import contextMenuWidget from "./services/context_menu.js"; import treeChangesService from "./services/branches.js"; import utils from "./services/utils.js"; -import treeService from "./services/tree.js"; import appContext from "./services/app_context.js"; window.glob.isDesktop = utils.isDesktop; @@ -37,7 +35,7 @@ $detail.on("click", ".close-detail-button",() => { }); async function showTree() { - const treeData = await treeService.loadTreeData(); + const treeData = await treeBuilder.prepareTree(); $tree.fancytree({ autoScroll: true, diff --git a/src/public/javascripts/services/app_context.js b/src/public/javascripts/services/app_context.js index 00ff91600..fe9248d5b 100644 --- a/src/public/javascripts/services/app_context.js +++ b/src/public/javascripts/services/app_context.js @@ -20,7 +20,6 @@ import GlobalMenuWidget from "../widgets/global_menu.js"; import RowFlexContainer from "../widgets/row_flex_container.js"; import StandardTopWidget from "../widgets/standard_top_widget.js"; import treeCache from "./tree_cache.js"; -import treeService from "./tree.js"; import NotePathsWidget from "../widgets/note_paths.js"; import RunScriptButtonsWidget from "../widgets/run_script_buttons.js"; import ProtectedNoteSwitchWidget from "../widgets/protected_note_switch.js"; @@ -392,6 +391,12 @@ class AppContext { removeAllTabsExceptForThis() { // TODO } + + async protectedSessionStartedListener() { + await treeCache.loadInitialTree(); + + this.trigger('treeCacheReloaded'); + } } const appContext = new AppContext(); diff --git a/src/public/javascripts/services/spaced_update.js b/src/public/javascripts/services/spaced_update.js index ed67f8a2b..54029ce4f 100644 --- a/src/public/javascripts/services/spaced_update.js +++ b/src/public/javascripts/services/spaced_update.js @@ -7,7 +7,7 @@ export default class SpacedUpdate { } scheduleUpdate() { - if (!this.changeForbidden) { + if (!this.changeForbidden) {console.trace(); this.changed = true; setTimeout(() => this.triggerUpdate()); } diff --git a/src/public/javascripts/services/tab_context.js b/src/public/javascripts/services/tab_context.js index 579fe478f..0148cf7db 100644 --- a/src/public/javascripts/services/tab_context.js +++ b/src/public/javascripts/services/tab_context.js @@ -46,10 +46,7 @@ class TabContext extends Component { await this.trigger('beforeNoteSwitch', {tabId: this.tabId}, true); this.notePath = notePath; - const noteId = treeService.getNoteIdFromNotePath(notePath); - - /** @property {NoteShort} */ - this.note = await treeCache.getNote(noteId); + this.noteId = treeService.getNoteIdFromNotePath(notePath); //this.cleanup(); // esp. on windows autocomplete is not getting closed automatically @@ -75,8 +72,9 @@ class TabContext extends Component { this.trigger('openTabsChanged'); } - get noteId() { - return this.note && this.note.noteId; + /** @property {NoteShort} */ + get note() { + return treeCache.notes[this.noteId]; } /** @return {NoteComplement} */ diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js index d081376a6..b4ee5779b 100644 --- a/src/public/javascripts/services/tree.js +++ b/src/public/javascripts/services/tree.js @@ -37,6 +37,7 @@ async function setNodeTitleWithPrefix(node) { node.setTitle(utils.escapeHtml(title)); } +// FIXME: unused? /** @return {FancytreeNode} */ async function activateNote(notePath, noteLoadedListener) { utils.assertArguments(notePath); @@ -291,14 +292,6 @@ function getHashValueFromAddress() { return str.split("-"); } -async function loadTreeData() { - const resp = await server.get('tree'); - - treeCache.load(resp.notes, resp.branches, resp.attributes); - - return await treeBuilder.prepareTree(); -} - function setProtected(noteId, isProtected) { appContext.getMainNoteTree().getNodesByNoteId(noteId).map(node => { node.data.isProtected = isProtected; @@ -595,7 +588,6 @@ export default { setPrefix, createNote, sortAlphabetically, - loadTreeData, treeInitialized, resolveNotePath, getSomeNotePath, diff --git a/src/public/javascripts/services/tree_builder.js b/src/public/javascripts/services/tree_builder.js index 41f4f9c31..be9d3fd1a 100644 --- a/src/public/javascripts/services/tree_builder.js +++ b/src/public/javascripts/services/tree_builder.js @@ -4,6 +4,8 @@ import ws from "./ws.js"; import hoistedNoteService from "./hoisted_note.js"; async function prepareTree() { + await treeCache.initializedPromise; + const hoistedNoteId = await hoistedNoteService.getHoistedNoteId(); let hoistedBranch; diff --git a/src/public/javascripts/services/tree_cache.js b/src/public/javascripts/services/tree_cache.js index 6c7dfc390..7fe0a54ba 100644 --- a/src/public/javascripts/services/tree_cache.js +++ b/src/public/javascripts/services/tree_cache.js @@ -4,6 +4,7 @@ import Attribute from "../entities/attribute.js"; import server from "./server.js"; import {LoadResults} from "./load_results.js"; import NoteComplement from "../entities/note_complement.js"; +import appContext from "./app_context.js"; /** * TreeCache keeps a read only cache of note tree structure in frontend's memory. @@ -15,10 +16,14 @@ import NoteComplement from "../entities/note_complement.js"; */ class TreeCache { constructor() { - this.init(); + this.initializedPromise = this.loadInitialTree(); } - init() { + async loadInitialTree() { + const {notes, branches, attributes} = await server.get('tree'); + + // clear the cache only directly before adding new content which is important for e.g. switching to protected session + /** @type {Object.} */ this.notes = {}; @@ -30,12 +35,8 @@ class TreeCache { /** @type {Object.>} */ this.noteComplementPromises = {}; - } - load(noteRows, branchRows, attributeRows) { - this.init(); - - this.addResp(noteRows, branchRows, attributeRows); + this.addResp(notes, branches, attributes); } addResp(noteRows, branchRows, attributeRows) { @@ -350,7 +351,6 @@ class TreeCache { loadResults.addNoteRevision(sync.entityId, sync.noteId, sync.sourceId); }); - const appContext = (await import('./app_context.js')).default; appContext.trigger('entitiesReloaded', {loadResults}); } } diff --git a/src/public/javascripts/widgets/note_detail.js b/src/public/javascripts/widgets/note_detail.js index 0fce2d2b0..0753ce9b6 100644 --- a/src/public/javascripts/widgets/note_detail.js +++ b/src/public/javascripts/widgets/note_detail.js @@ -214,10 +214,6 @@ export default class NoteDetailWidget extends TabAwareWidget { this.refresh(); } - protectedSessionStartedListener() { - this.refresh(); - } - async entitiesReloadedListener({loadResults}) { // we should test what happens when the loaded note is deleted diff --git a/src/public/javascripts/widgets/note_title.js b/src/public/javascripts/widgets/note_title.js index e90e9bf09..a284b43fd 100644 --- a/src/public/javascripts/widgets/note_title.js +++ b/src/public/javascripts/widgets/note_title.js @@ -4,7 +4,6 @@ import protectedSessionHolder from "../services/protected_session_holder.js"; import treeCache from "../services/tree_cache.js"; import server from "../services/server.js"; import SpacedUpdate from "../services/spaced_update.js"; -import appContext from "../services/app_context.js"; const TPL = `
@@ -75,9 +74,7 @@ export default class NoteTitleWidget extends TabAwareWidget { async refreshWithNote(note) { this.$noteTitle.val(note.title); - if (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) { - this.$noteTitle.prop("readonly", true); - } + this.$noteTitle.prop("readonly", note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()); } async beforeNoteSwitchListener({tabId}) { diff --git a/src/public/javascripts/widgets/note_tree.js b/src/public/javascripts/widgets/note_tree.js index 007c7e786..60492ac5c 100644 --- a/src/public/javascripts/widgets/note_tree.js +++ b/src/public/javascripts/widgets/note_tree.js @@ -61,7 +61,7 @@ export default class NoteTreeWidget extends TabAwareWidget { } }); - treeService.loadTreeData().then(treeData => this.initFancyTree($tree, treeData)); + treeBuilder.prepareTree().then(treeData => this.initFancyTree($tree, treeData)); return $widget; } @@ -577,8 +577,8 @@ export default class NoteTreeWidget extends TabAwareWidget { await server.put('branches/' + branchId + '/expanded/' + expandedNum); } - async reloadTreeListener() { - const notes = await treeService.loadTreeData(); + async reloadTreeFromCache() { + const notes = await treeBuilder.prepareTree(); const activeNode = this.getActiveNode(); @@ -594,10 +594,10 @@ export default class NoteTreeWidget extends TabAwareWidget { } hoistedNoteChangedListener() { - this.reloadTreeListener(); + this.reloadTreeFromCache(); } - protectedSessionStartedListener() { - this.reloadTreeListener(); + treeCacheReloadedListener() { + this.reloadTreeFromCache(); } } \ No newline at end of file diff --git a/src/public/javascripts/widgets/tab_aware_widget.js b/src/public/javascripts/widgets/tab_aware_widget.js index 7e0de9da3..a064958b8 100644 --- a/src/public/javascripts/widgets/tab_aware_widget.js +++ b/src/public/javascripts/widgets/tab_aware_widget.js @@ -59,4 +59,8 @@ export default class TabAwareWidget extends BasicWidget { this.activeTabChanged(); } + + treeCacheReloadedListener() { + this.refresh(); + } } \ No newline at end of file diff --git a/src/public/javascripts/widgets/tab_row.js b/src/public/javascripts/widgets/tab_row.js index d44bc4327..98a1be2ff 100644 --- a/src/public/javascripts/widgets/tab_row.js +++ b/src/public/javascripts/widgets/tab_row.js @@ -582,8 +582,8 @@ export default class TabRowWidget extends BasicWidget { if (currentIndex !== destinationIndex) { this.animateTabMove(tabEl, currentIndex, destinationIndex); } - }) - }) + }); + }); } animateTabMove(tabEl, originIndex, destinationIndex) { @@ -619,7 +619,7 @@ export default class TabRowWidget extends BasicWidget { array.forEach((v, i) => { if (Math.abs(value - v) < closest) { closest = Math.abs(value - v); - closestIndex = i + closestIndex = i; } }); @@ -662,7 +662,11 @@ export default class TabRowWidget extends BasicWidget { } } - protectedSessionStartedListener() { - // FIXME + treeCacheReloadedListener() { + for (const tabContext of this.appContext.getTabContexts()) { + const $tab = this.getTabById(tabContext.tabId); + + this.updateTab($tab, tabContext.note); + } } } \ No newline at end of file diff --git a/src/public/javascripts/widgets/type_widgets/code.js b/src/public/javascripts/widgets/type_widgets/code.js index 7fc6ac72a..1ade09b26 100644 --- a/src/public/javascripts/widgets/type_widgets/code.js +++ b/src/public/javascripts/widgets/type_widgets/code.js @@ -129,7 +129,9 @@ export default class CodeTypeWidget extends TypeWidget { cleanup() { if (this.codeEditor) { - this.codeEditor.setValue(''); + this.spacedUpdate.allowUpdateWithoutChange(() => { + this.codeEditor.setValue(''); + }); } } diff --git a/src/public/javascripts/widgets/type_widgets/relation_map.js b/src/public/javascripts/widgets/type_widgets/relation_map.js index 7a5363480..cba4eb01e 100644 --- a/src/public/javascripts/widgets/type_widgets/relation_map.js +++ b/src/public/javascripts/widgets/type_widgets/relation_map.js @@ -576,10 +576,6 @@ export default class RelationMapTypeWidget extends TypeWidget { }); } - async refresh() { - await this.loadNotesAndRelations(); - } - getZoom() { const matrixRegex = /matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*-?\d*\.?\d+,\s*-?\d*\.?\d+,\s*-?\d*\.?\d+\)/; diff --git a/src/public/javascripts/widgets/type_widgets/text.js b/src/public/javascripts/widgets/type_widgets/text.js index df3ae96e0..303fac754 100644 --- a/src/public/javascripts/widgets/type_widgets/text.js +++ b/src/public/javascripts/widgets/type_widgets/text.js @@ -174,7 +174,9 @@ export default class TextTypeWidget extends TypeWidget { cleanup() { if (this.textEditor) { - this.textEditor.setData(''); + this.spacedUpdate.allowUpdateWithoutChange(() => { + this.textEditor.setData(''); + }); } } diff --git a/src/routes/api/branches.js b/src/routes/api/branches.js index fb59454e0..b24eaeb30 100644 --- a/src/routes/api/branches.js +++ b/src/routes/api/branches.js @@ -16,13 +16,13 @@ const TaskContext = require('../../services/task_context'); async function moveBranchToParent(req) { const {branchId, parentNoteId} = req.params; - const noteToMove = await tree.getBranch(branchId); + const branchToMove = await tree.getBranch(branchId); - if (noteToMove.parentNoteId === parentNoteId) { + if (branchToMove.parentNoteId === parentNoteId) { return { success: true }; // no-op } - const validationResult = await tree.validateParentChild(parentNoteId, noteToMove.noteId, branchId); + const validationResult = await tree.validateParentChild(parentNoteId, branchToMove.noteId, branchId); if (!validationResult.success) { return [200, validationResult]; @@ -31,11 +31,11 @@ async function moveBranchToParent(req) { const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [parentNoteId]); const newNotePos = maxNotePos === null ? 0 : maxNotePos + 10; - const newBranch = noteToMove.getClone(parentNoteId, newNotePos); + const newBranch = branchToMove.createClone(parentNoteId, newNotePos); await newBranch.save(); - noteToMove.isDeleted = true; - await noteToMove.save(); + branchToMove.isDeleted = true; + await branchToMove.save(); return { success: true }; } @@ -43,10 +43,10 @@ async function moveBranchToParent(req) { async function moveBranchBeforeNote(req) { const {branchId, beforeBranchId} = req.params; - const noteToMove = await tree.getBranch(branchId); + const branchToMove = await tree.getBranch(branchId); const beforeNote = await tree.getBranch(beforeBranchId); - const validationResult = await tree.validateParentChild(beforeNote.parentNoteId, noteToMove.noteId, branchId); + const validationResult = await tree.validateParentChild(beforeNote.parentNoteId, branchToMove.noteId, branchId); if (!validationResult.success) { return [200, validationResult]; @@ -59,16 +59,16 @@ async function moveBranchBeforeNote(req) { await syncTableService.addNoteReorderingSync(beforeNote.parentNoteId); - if (noteToMove.parentNoteId === beforeNote.parentNoteId) { - noteToMove.notePosition = beforeNote.notePosition; - await noteToMove.save(); + if (branchToMove.parentNoteId === beforeNote.parentNoteId) { + branchToMove.notePosition = beforeNote.notePosition; + await branchToMove.save(); } else { - const newBranch = noteToMove.getClone(beforeNote.parentNoteId, beforeNote.notePosition); + const newBranch = branchToMove.createClone(beforeNote.parentNoteId, beforeNote.notePosition); await newBranch.save(); - noteToMove.isDeleted = true; - await noteToMove.save(); + branchToMove.isDeleted = true; + await branchToMove.save(); } return { success: true }; @@ -77,10 +77,10 @@ async function moveBranchBeforeNote(req) { async function moveBranchAfterNote(req) { const {branchId, afterBranchId} = req.params; - const noteToMove = await tree.getBranch(branchId); + const branchToMove = await tree.getBranch(branchId); const afterNote = await tree.getBranch(afterBranchId); - const validationResult = await tree.validateParentChild(afterNote.parentNoteId, noteToMove.noteId, branchId); + const validationResult = await tree.validateParentChild(afterNote.parentNoteId, branchToMove.noteId, branchId); if (!validationResult.success) { return [200, validationResult]; @@ -95,16 +95,16 @@ async function moveBranchAfterNote(req) { const movedNotePosition = afterNote.notePosition + 10; - if (noteToMove.parentNoteId === afterNote.parentNoteId) { - noteToMove.notePosition = movedNotePosition; - await noteToMove.save(); + if (branchToMove.parentNoteId === afterNote.parentNoteId) { + branchToMove.notePosition = movedNotePosition; + await branchToMove.save(); } else { - const newBranch = noteToMove.getClone(afterNote.parentNoteId, movedNotePosition); + const newBranch = branchToMove.createClone(afterNote.parentNoteId, movedNotePosition); await newBranch.save(); - noteToMove.isDeleted = true; - await noteToMove.save(); + branchToMove.isDeleted = true; + await branchToMove.save(); } return { success: true }; diff --git a/src/services/ws.js b/src/services/ws.js index 76ce1d158..5a5616648 100644 --- a/src/services/ws.js +++ b/src/services/ws.js @@ -4,6 +4,7 @@ const log = require('./log'); const sql = require('./sql'); const cls = require('./cls'); const syncMutexService = require('./sync_mutex'); +const protectedSessionService = require('./protected_session'); let webSocketServer; let lastAcceptedSyncIds = {}; @@ -80,6 +81,10 @@ async function fillInAdditionalProperties(sync) { sync.entity = await sql.getRow(`SELECT * FROM branches WHERE branchId = ?`, [sync.entityId]); } else if (sync.entityName === 'notes') { sync.entity = await sql.getRow(`SELECT * FROM notes WHERE noteId = ?`, [sync.entityId]); + + if (sync.entity.isProtected) { + sync.entity.title = protectedSessionService.decryptString(sync.entity.title); + } } else if (sync.entityName === 'note_revisions') { sync.noteId = await sql.getValue(`SELECT noteId FROM note_revisions