Add DOM, DOMObserver and VueInjector to the plugin API

This commit is contained in:
Samuel Elliott 2018-05-14 16:33:24 +01:00
parent 9915ef8b19
commit 9eb8eaa906
No known key found for this signature in database
GPG Key ID: 8420C7CDE43DC4D6
3 changed files with 28 additions and 33 deletions

View File

@ -10,7 +10,7 @@
import { EmoteModule } from 'builtin'; import { EmoteModule } from 'builtin';
import { SettingsSet, SettingsCategory, Setting, SettingsScheme } from 'structs'; import { SettingsSet, SettingsCategory, Setting, SettingsScheme } from 'structs';
import { BdMenu, Modals, DOM, Reflection } from 'ui'; import { BdMenu, Modals, DOM, DOMObserver, Reflection, VueInjector } from 'ui';
import * as CommonComponents from 'commoncomponents'; import * as CommonComponents from 'commoncomponents';
import { Utils, Filters, ClientLogger as Logger, ClientIPC, AsyncEventEmitter } from 'common'; import { Utils, Filters, ClientLogger as Logger, ClientIPC, AsyncEventEmitter } from 'common';
import Settings from './settings'; import Settings from './settings';
@ -66,6 +66,12 @@ export default class PluginApi {
get ReactComponents() { return ReactComponents } get ReactComponents() { return ReactComponents }
get ReactHelpers() { return ReactHelpers } get ReactHelpers() { return ReactHelpers }
get Reflection() { return Reflection } get Reflection() { return Reflection }
get DOM() { return DOM }
get VueInjector() { return VueInjector }
get observer() {
return this._observer || (this._observer = new DOMObserver());
}
/** /**
* Logger * Logger

View File

@ -30,12 +30,15 @@ class BdNode {
} }
} }
class DOMObserver { export class DOMObserver {
constructor(root, options) {
constructor() {
this.observe = this.observe.bind(this); this.observe = this.observe.bind(this);
this.subscribe = this.subscribe.bind(this); this.subscribe = this.subscribe.bind(this);
this.observerCallback = this.observerCallback.bind(this); this.observerCallback = this.observerCallback.bind(this);
this.root = root || document.getElementById('app-mount');
this.options = options || { attributes: true, childList: true, subtree: true };
this.observer = new MutationObserver(this.observerCallback); this.observer = new MutationObserver(this.observerCallback);
this.observe(); this.observe();
} }
@ -47,7 +50,9 @@ class DOMObserver {
if (!f) continue; if (!f) continue;
if (sub.type && sub.type === 'filter' && !f.length) continue; if (sub.type && sub.type === 'filter' && !f.length) continue;
sub.callback(f); sub.callback(f);
} catch(err) {} } catch (err) {
Logger.warn('DOMObserver', [`Error in observer callback ${sub.id}`, err]);
}
} }
} }
@ -55,14 +60,6 @@ class DOMObserver {
this.observer.observe(this.root, this.options); this.observer.observe(this.root, this.options);
} }
get root() {
return document.getElementById('app-mount');
}
get options() {
return { attributes: true, childList: true, subtree: true };
}
get subscriptions() { get subscriptions() {
return this._subscriptions || (this._subscriptions = []); return this._subscriptions || (this._subscriptions = []);
} }
@ -78,11 +75,14 @@ class DOMObserver {
} }
unsubscribe(id) { unsubscribe(id) {
const index = this.subscriptions.find(sub => sub.id === id); const index = this.subscriptions.findIndex(sub => sub.id === id);
if (index < 0) return; if (index < 0) return;
this.subscriptions.splice(index, 1); this.subscriptions.splice(index, 1);
} }
unsubscribeAll() {
this.subscriptions.splice(index, this.subscriptions.length);
}
} }
class Manip { class Manip {
@ -95,6 +95,7 @@ class Manip {
document.execCommand('insertText', false, text); document.execCommand('insertText', false, text);
if (activeElement && refocus) activeElement.focus(); if (activeElement && refocus) activeElement.focus();
} }
static getText() { static getText() {
const txt = document.querySelector('.chat form textarea'); const txt = document.querySelector('.chat form textarea');
if (!txt) return ''; if (!txt) return '';
@ -112,24 +113,12 @@ export default class DOM {
return this._observer || (this._observer = new DOMObserver()); return this._observer || (this._observer = new DOMObserver());
} }
static get bdHead() { static get bdHead() { return this.getElement('bd-head') || this.createElement('bd-head').appendTo('head') }
return this.getElement('bd-head') || this.createElement('bd-head').appendTo('head'); static get bdBody() { return this.getElement('bd-body') || this.createElement('bd-body').appendTo('body') }
} static get bdStyles() { return this.getElement('bd-styles') || this.createElement('bd-styles').appendTo(this.bdHead) }
static get bdBody() { static get bdThemes() { return this.getElement('bd-themes') || this.createElement('bd-themes').appendTo(this.bdHead) }
return this.getElement('bd-body') || this.createElement('bd-body').appendTo('body'); static get bdTooltips() { return this.getElement('bd-tooltips') || this.createElement('bd-tooltips').appendTo(this.bdBody) }
} static get bdModals() { return this.getElement('bd-modals') || this.createElement('bd-modals').appendTo(this.bdBody) }
static get bdStyles() {
return this.getElement('bd-styles') || this.createElement('bd-styles').appendTo(this.bdHead);
}
static get bdThemes() {
return this.getElement('bd-themes') || this.createElement('bd-themes').appendTo(this.bdHead);
}
static get bdTooltips() {
return this.getElement('bd-tooltips') || this.createElement('bd-tooltips').appendTo(this.bdBody);
}
static get bdModals() {
return this.getElement('bd-modals') || this.createElement('bd-modals').appendTo(this.bdBody);
}
static getElement(e) { static getElement(e) {
if (e instanceof BdNode) return e.element; if (e instanceof BdNode) return e.element;

View File

@ -1,4 +1,4 @@
export { default as DOM } from './dom'; export { default as DOM, DOMObserver } from './dom';
export { default as BdUI } from './bdui'; export { default as BdUI } from './bdui';
export { default as VueInjector } from './vueinjector'; export { default as VueInjector } from './vueinjector';
export { default as BdMenu, BdMenuItems } from './bdmenu'; export { default as BdMenu, BdMenuItems } from './bdmenu';