improvements in widgets rendering - individual widget render is now async while composing them together to the sidebar is sync which solves some race problems

This commit is contained in:
zadam 2019-09-08 09:40:29 +02:00
parent 2dae9b9621
commit 90afb2a1ee
3 changed files with 25 additions and 14 deletions

View File

@ -7,6 +7,9 @@ const RELATION = 'relation';
const RELATION_DEFINITION = 'relation-definition'; const RELATION_DEFINITION = 'relation-definition';
/** /**
* FIXME: rethink how attributes are cached in Note entities since they are long lived inside the cache.
* Attribute cache should be limited to "transaction".
*
* This note's representation is used in note tree and is kept in TreeCache. * This note's representation is used in note tree and is kept in TreeCache.
*/ */
class NoteShort { class NoteShort {

View File

@ -52,14 +52,6 @@ class Sidebar {
return; return;
} }
for (const widget of this.widgets) {
if (widget.cleanup) {
widget.cleanup();
}
}
this.widgets = [];
const widgetClasses = (await Promise.all([ const widgetClasses = (await Promise.all([
import("../widgets/note_info.js"), import("../widgets/note_info.js"),
import("../widgets/link_map.js"), import("../widgets/link_map.js"),
@ -80,12 +72,14 @@ class Sidebar {
widgetClasses.push(widgetClass); widgetClasses.push(widgetClass);
} }
const widgets = [];
for (const widgetClass of widgetClasses) { for (const widgetClass of widgetClasses) {
try { try {
const widget = new widgetClass(this.ctx, options, this.state); const widget = new widgetClass(this.ctx, options, this.state);
if (await widget.isEnabled()) { if (await widget.isEnabled()) {
this.widgets.push(widget); widgets.push(widget);
} }
} }
catch (e) { catch (e) {
@ -93,16 +87,29 @@ class Sidebar {
} }
} }
this.renderWidgets(widgets);
}
// it's important that this method is sync so that the whole render-update is atomic
// otherwise we could get race issues (doubled widgets etc.)
renderWidgets(widgets) {
// cleanup old widgets
for (const widget of this.widgets) {
if (widget.cleanup) {
widget.cleanup();
}
}
this.widgets = widgets;
this.widgets.sort((a, b) => a.getPosition() < b.getPosition() ? -1 : 1); this.widgets.sort((a, b) => a.getPosition() < b.getPosition() ? -1 : 1);
const widgetsToAppend = []; const widgetsToAppend = [];
for (const widget of this.widgets) { for (const widget of this.widgets) {
try { try {
const $el = await widget.render(); const $el = widget.render();
widgetsToAppend.push($el); widgetsToAppend.push($el);
} } catch (e) {
catch (e) {
ws.logError(`Error while rendering widget ${widget.widgetName}: ${e.message}`); ws.logError(`Error while rendering widget ${widget.widgetName}: ${e.message}`);
} }
} }

View File

@ -43,7 +43,7 @@ class StandardWidget {
getPosition() { return this.widgetOptions.position; } getPosition() { return this.widgetOptions.position; }
async render() { render() {
const widgetId = `tab-${this.ctx.tabId}-widget-${this.widgetName}`; const widgetId = `tab-${this.ctx.tabId}-widget-${this.widgetName}`;
this.$widget = $(WIDGET_TPL); this.$widget = $(WIDGET_TPL);
@ -73,7 +73,8 @@ class StandardWidget {
this.$headerActions = this.$widget.find('.widget-header-actions'); this.$headerActions = this.$widget.find('.widget-header-actions');
this.$headerActions.append(...this.getHeaderActions()); this.$headerActions.append(...this.getHeaderActions());
await this.renderBody(); // actual rendering is async
this.renderBody();
return this.$widget; return this.$widget;
} }