From b00a9f441568f5fd2568c85fee7d820f71d7e4d1 Mon Sep 17 00:00:00 2001 From: zadam Date: Sat, 18 Jan 2020 18:01:16 +0100 Subject: [PATCH] progress --- package-lock.json | 6 ++-- .../javascripts/services/app_context.js | 36 ++----------------- .../javascripts/services/tab_context.js | 9 ++--- .../javascripts/widgets/basic_widget.js | 16 +++------ src/public/javascripts/widgets/component.js | 10 ++++-- .../widgets/detail/note_detail_text.js | 36 +++++++------------ src/public/javascripts/widgets/note_detail.js | 31 +++++++++------- src/public/javascripts/widgets/note_tree.js | 23 +++++++++++- .../widgets/promoted_attributes.js | 6 ++-- .../javascripts/widgets/standard_widget.js | 2 +- .../javascripts/widgets/tab_aware_widget.js | 14 ++++++-- .../javascripts/widgets/tab_caching_widget.js | 4 ++- 12 files changed, 91 insertions(+), 102 deletions(-) diff --git a/package-lock.json b/package-lock.json index 83323462b..63d2c41f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2777,9 +2777,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.11.tgz", - "integrity": "sha512-dNd2pp8qTzzNLAs3O8nH3iU9DG9866KHq9L3ISPB7DOGERZN81nW/5/g/KzMJpCU8jrbCiMRBzV9/sCEdRosig==", + "version": "10.17.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz", + "integrity": "sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==", "dev": true } } diff --git a/src/public/javascripts/services/app_context.js b/src/public/javascripts/services/app_context.js index edef7058d..5c8e8d24d 100644 --- a/src/public/javascripts/services/app_context.js +++ b/src/public/javascripts/services/app_context.js @@ -127,6 +127,8 @@ class AppContext { activateNote(notePath) { const activeTabContext = this.getActiveTabContext(); + console.log("Setting activeTabContext to " + notePath); + activeTabContext.setNote(notePath); this._setTitleBar(); @@ -209,36 +211,6 @@ class AppContext { } } - async showTab(tabId) { - for (const ctx of this.tabContexts) { - if (ctx.tabId === tabId) { - await ctx.show(); - } else { - ctx.hide(); - } - } - - const oldActiveNode = this.getMainNoteTree().getActiveNode(); - - if (oldActiveNode) { - oldActiveNode.setActive(false); - } - - const newActiveTabContext = this.getActiveTabContext(); - - if (newActiveTabContext && newActiveTabContext.notePath) { - const newActiveNode = await this.getMainNoteTree().getNodeFromPath(newActiveTabContext.notePath); - - if (newActiveNode) { - if (!newActiveNode.isVisible()) { - await this.getMainNoteTree().expandToNote(newActiveTabContext.notePath); - } - - newActiveNode.setActive(true, {noEvents: true}); - } - } - } - /** * @return {NoteTreeWidget} */ @@ -343,10 +315,6 @@ class AppContext { this.openEmptyTab(); } - async activeTabChangedListener({tabId}) { - await this.showTab(tabId); - } - async tabRemoveListener({tabId}) { this.tabContexts.filter(nc => nc.tabId === tabId) .forEach(tc => tc.remove()); diff --git a/src/public/javascripts/services/tab_context.js b/src/public/javascripts/services/tab_context.js index c7ed02219..0e165a3b4 100644 --- a/src/public/javascripts/services/tab_context.js +++ b/src/public/javascripts/services/tab_context.js @@ -44,13 +44,9 @@ class TabContext extends Component { this.tabRow.updateTab(this.$tab[0], {title: this.note.title}); - if (!this.initialized) { - return; - } - this.setupClasses(); - this.cleanup(); // esp. on windows autocomplete is not getting closed automatically + //this.cleanup(); // esp. on windows autocomplete is not getting closed automatically setTimeout(async () => { // we include the note into recent list only if the user stayed on the note at least 5 seconds @@ -64,11 +60,10 @@ class TabContext extends Component { bundleService.executeRelationBundles(this.note, 'runOnNoteView', this); - appContext.trigger('activeNoteChanged'); + this.trigger('tabNoteSwitched', {tabId: this.tabId}); } async show() { - await this.setNote(this.notePath); } hide() { diff --git a/src/public/javascripts/widgets/basic_widget.js b/src/public/javascripts/widgets/basic_widget.js index b62bf9112..2f5c5a40b 100644 --- a/src/public/javascripts/widgets/basic_widget.js +++ b/src/public/javascripts/widgets/basic_widget.js @@ -1,28 +1,20 @@ import Component from "./component.js"; class BasicWidget extends Component { - constructor(appContext) { - super(appContext); - this.widgetId = `widget-${this.constructor.name}`; - } - renderTo($parent) { + this.$parent = $parent; + $parent.append(this.render()); } render() { - // actual rendering is async - this.$widget = this.doRender(); - -// $widget.attr('id', this.widgetId); - - return this.$widget; + return this.doRender(); } /** * for overriding */ - doRender() {} + async doRender() {} toggle(show) { this.$widget.toggle(show); diff --git a/src/public/javascripts/widgets/component.js b/src/public/javascripts/widgets/component.js index 312033740..83163efc2 100644 --- a/src/public/javascripts/widgets/component.js +++ b/src/public/javascripts/widgets/component.js @@ -1,16 +1,22 @@ export default class Component { /** @param {AppContext} appContext */ constructor(appContext) { + this.componentId = `component-${this.constructor.name}`; this.appContext = appContext; /** @type Component[] */ this.children = []; + this.initialized = Promise.resolve(); } - eventReceived(name, data) { + async eventReceived(name, data) { + await this.initialized; + + console.log(`Received ${name} to ${this.componentId}`); + const fun = this[name + 'Listener']; if (typeof fun === 'function') { - fun.call(this, data); + await fun.call(this, data); } for (const child of this.children) { diff --git a/src/public/javascripts/widgets/detail/note_detail_text.js b/src/public/javascripts/widgets/detail/note_detail_text.js index 0d8fbbc64..772bc56a9 100644 --- a/src/public/javascripts/widgets/detail/note_detail_text.js +++ b/src/public/javascripts/widgets/detail/note_detail_text.js @@ -73,11 +73,9 @@ const TPL = ` `; class NoteDetailText extends TabAwareWidget { - render() { + doRender() { this.$widget = $(TPL); this.$editor = this.$widget.find('.note-detail-text-editor'); - this.textEditorPromise = null; - this.textEditor = null; this.$widget.on("dblclick", "img", e => { const $img = $(e.target); @@ -95,26 +93,11 @@ class NoteDetailText extends TabAwareWidget { } }); - if (!this.textEditorPromise) { - this.textEditorPromise = this.initEditor(); - } + this.initialized = this.initEditor(); return this.$widget; } - async activeNoteChanged() { - await this.textEditorPromise; - - // lazy loading above can take time and tab might have been already switched to another note - if (this.tabContext.note && this.tabContext.note.type === 'text') { - this.textEditor.isReadOnly = await this.isReadOnly(); - - this.$widget.show(); - - this.textEditor.setData(this.tabContext.note.content); - } - } - async initEditor() { await libraryLoader.requireLibrary(libraryLoader.CKEDITOR); @@ -133,7 +116,7 @@ class NoteDetailText extends TabAwareWidget { // display of $widget in both branches. this.$widget.show(); - const textEditorInstance = await BalloonEditor.create(this.$editor[0], { + this.textEditor = await BalloonEditor.create(this.$editor[0], { placeholder: "Type the content of your note here ...", mention: mentionSetup, codeBlock: { @@ -143,12 +126,19 @@ class NoteDetailText extends TabAwareWidget { if (glob.isDev && ENABLE_INSPECTOR) { await import('../../libraries/ckeditor/inspector.js'); - CKEditorInspector.attach(textEditorInstance); + CKEditorInspector.attach(this.textEditor); } + } - this.textEditor = textEditorInstance; + async noteSwitched() { + // lazy loading above can take time and tab might have been already switched to another note + if (this.tabContext.note && this.tabContext.note.type === 'text') { + this.textEditor.isReadOnly = await this.isReadOnly(); - //this.onNoteChange(() => this.tabContext.noteChanged()); + this.$widget.show(); + + this.textEditor.setData(this.tabContext.note.content); + } } getContent() { diff --git a/src/public/javascripts/widgets/note_detail.js b/src/public/javascripts/widgets/note_detail.js index 0be66791d..6169cabc6 100644 --- a/src/public/javascripts/widgets/note_detail.js +++ b/src/public/javascripts/widgets/note_detail.js @@ -34,6 +34,7 @@ export default class NoteDetailWidget extends TabAwareWidget { super(appContext); this.components = {}; + this.componentPromises = {}; } doRender() { @@ -42,13 +43,10 @@ export default class NoteDetailWidget extends TabAwareWidget { return this.$widget; } - async activeTabChanged() { + async noteSwitched() { await this.initComponent(/**disableAutoBook*/); for (const componentType in this.components) { - // FIXME - this.components[componentType].ctx = this.tabContext; - if (componentType !== this.type) { this.components[componentType].cleanup(); } @@ -57,7 +55,6 @@ export default class NoteDetailWidget extends TabAwareWidget { this.$widget.find('.note-detail-component').hide(); this.getComponent().show(); - await this.getComponent().render(); this.setupClasses(); } @@ -89,14 +86,24 @@ export default class NoteDetailWidget extends TabAwareWidget { async initComponent(disableAutoBook = false) { this.type = this.getComponentType(disableAutoBook); - if (!(this.type in this.components)) { - const clazz = await import(componentClasses[this.type]); - - this.components[this.type] = new clazz.default(this); - this.children.push(this.components[this.type]); - - this.$widget.append(this.components[this.type].render()); + if (!(this.type in this.componentPromises)) { + this.componentPromises[this.type] = this.reallyInitComponent(this.type); } + + await this.componentPromises[this.type]; + } + + async reallyInitComponent(type) { + const clazz = await import(componentClasses[type]); + + this.components[this.type] = new clazz.default(this.appContext); + this.children.push(this.components[this.type]); + + this.components[this.type].renderTo(this.$widget); + + this.components[this.type].setTabContext(this.tabContext); + + this.components[this.type].eventReceived('tabNoteSwitched', {tabId: this.tabContext.tabId}); } getComponentType(disableAutoBook) { diff --git a/src/public/javascripts/widgets/note_tree.js b/src/public/javascripts/widgets/note_tree.js index b0d5c4dce..ab206c644 100644 --- a/src/public/javascripts/widgets/note_tree.js +++ b/src/public/javascripts/widgets/note_tree.js @@ -13,6 +13,7 @@ import TreeContextMenu from "../services/tree_context_menu.js"; import treeChangesService from "../services/branches.js"; import ws from "../services/ws.js"; import appContext from "../services/app_context.js"; +import TabAwareWidget from "./tab_aware_widget.js"; const TPL = `
@@ -29,7 +30,7 @@ const TPL = `
`; -export default class NoteTreeWidget extends BasicWidget { +export default class NoteTreeWidget extends TabAwareWidget { constructor(appContext) { super(appContext); @@ -402,6 +403,26 @@ export default class NoteTreeWidget extends BasicWidget { collapseTreeListener() { this.collapseTree(); } + async activeTabChanged() { + const oldActiveNode = this.getActiveNode(); + + if (oldActiveNode) { + oldActiveNode.setActive(false); + } + + if (this.tabContext && this.tabContext.notePath) { + const newActiveNode = await this.getNodeFromPath(this.tabContext.notePath); + + if (newActiveNode) { + if (!newActiveNode.isVisible()) { + await this.expandToNote(this.tabContext.notePath); + } + + newActiveNode.setActive(true, {noEvents: true}); + } + } + } + async notesReloadedListener({ noteIds, activateNotePath }) { for (const noteId of noteIds) { for (const node of this.getNodesByNoteId(noteId)) { diff --git a/src/public/javascripts/widgets/promoted_attributes.js b/src/public/javascripts/widgets/promoted_attributes.js index 3b334e184..f28d1ddf7 100644 --- a/src/public/javascripts/widgets/promoted_attributes.js +++ b/src/public/javascripts/widgets/promoted_attributes.js @@ -28,11 +28,11 @@ const TPL = ` export default class PromotedAttributesWidget extends TabAwareWidget { doRender() { - const $widget = $(TPL); + this.$widget = $(TPL); - this.$container = $widget.find(".promoted-attributes"); + this.$container = this.$widget.find(".promoted-attributes"); - return $widget; + return this.$widget; } async activeTabChanged() { diff --git a/src/public/javascripts/widgets/standard_widget.js b/src/public/javascripts/widgets/standard_widget.js index 7c456fe9d..aa695ad35 100644 --- a/src/public/javascripts/widgets/standard_widget.js +++ b/src/public/javascripts/widgets/standard_widget.js @@ -33,7 +33,7 @@ class StandardWidget extends TabAwareWidget { //getPosition() { return this.widgetOptions.position; } render() { - const widgetInstanceId = this.widgetId + "-" + utils.randomString(10); + const widgetInstanceId = this.componentId + "-" + utils.randomString(10); this.$widget = $(WIDGET_TPL); this.$widget.find('[data-target]').attr('data-target', "#" + widgetInstanceId); diff --git a/src/public/javascripts/widgets/tab_aware_widget.js b/src/public/javascripts/widgets/tab_aware_widget.js index 47aae7526..8c9de87fa 100644 --- a/src/public/javascripts/widgets/tab_aware_widget.js +++ b/src/public/javascripts/widgets/tab_aware_widget.js @@ -1,13 +1,21 @@ import BasicWidget from "./basic_widget.js"; export default class TabAwareWidget extends BasicWidget { - constructor(appContext, tabContext = null) { - super(appContext); - + setTabContext(tabContext) { /** @var {TabContext} */ this.tabContext = tabContext; + + this.eventReceived('tabNoteSwitched', {tabId: this.tabContext.tabId}); } + tabNoteSwitchedListener({tabId}) { + if (this.tabContext && tabId === this.tabContext.tabId) { + this.noteSwitched(); + } + } + + noteSwitched() {} + // to override activeTabChanged() {} diff --git a/src/public/javascripts/widgets/tab_caching_widget.js b/src/public/javascripts/widgets/tab_caching_widget.js index 897488fd5..47ec865fa 100644 --- a/src/public/javascripts/widgets/tab_caching_widget.js +++ b/src/public/javascripts/widgets/tab_caching_widget.js @@ -23,8 +23,10 @@ export default class TabCachingWidget extends TabAwareWidget { if (!widget) { widget = this.widgets[this.tabContext.tabId] = this.widgetFactory(); + this.children.push(widget); widget.renderTo(this.$parent); - widget.activeTabChangedListener(); + + widget.setTabContext(this.tabContext); } widget.toggle(true);