72 lines
1.9 KiB
JavaScript
72 lines
1.9 KiB
JavaScript
import { cancel } from "@ember/runloop";
|
|
import { scheduleOnce } from "@ember/runloop";
|
|
import { diff, patch } from "virtual-dom";
|
|
import { queryRegistry } from "discourse/widgets/widget";
|
|
import DirtyKeys from "discourse/lib/dirty-keys";
|
|
import ENV from "discourse-common/config/environment";
|
|
|
|
export default class WidgetGlue {
|
|
constructor(name, register, attrs) {
|
|
this._tree = null;
|
|
this._rootNode = null;
|
|
this.register = register;
|
|
this.attrs = attrs;
|
|
this._timeout = null;
|
|
this.dirtyKeys = new DirtyKeys(name);
|
|
|
|
this._widgetClass =
|
|
queryRegistry(name) || this.register.lookupFactory(`widget:${name}`);
|
|
if (!this._widgetClass) {
|
|
// eslint-disable-next-line no-console
|
|
console.error(`Error: Could not find widget: ${name}`);
|
|
}
|
|
}
|
|
|
|
appendTo(elem) {
|
|
this._rootNode = elem;
|
|
this.queueRerender();
|
|
}
|
|
|
|
queueRerender() {
|
|
this._timeout = scheduleOnce("render", this, this.rerenderWidget);
|
|
}
|
|
|
|
rerenderWidget() {
|
|
cancel(this._timeout);
|
|
|
|
// in test mode return early if store cannot be found
|
|
if (ENV.environment === "test") {
|
|
try {
|
|
this.register.lookup("service:store");
|
|
} catch (e) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
const newTree = new this._widgetClass(this.attrs, this.register, {
|
|
dirtyKeys: this.dirtyKeys
|
|
});
|
|
const patches = diff(this._tree || this._rootNode, newTree);
|
|
|
|
newTree._rerenderable = this;
|
|
this._rootNode = patch(this._rootNode, patches);
|
|
this._tree = newTree;
|
|
}
|
|
|
|
cleanUp() {
|
|
const widgets = [];
|
|
const findWidgets = widget => {
|
|
widget.vnode.children.forEach(child => {
|
|
if (child.constructor.name === "CustomWidget") {
|
|
widgets.push(child);
|
|
findWidgets(child, widgets);
|
|
}
|
|
});
|
|
};
|
|
findWidgets(this._tree, widgets);
|
|
widgets.reverse().forEach(widget => widget.destroy());
|
|
|
|
cancel(this._timeout);
|
|
}
|
|
}
|