From 47637eca75459ad62faff65fd83d4598ed1ecc7d Mon Sep 17 00:00:00 2001 From: Samuel Elliott Date: Sun, 4 Mar 2018 21:49:35 +0000 Subject: [PATCH] Fix settingsset.findSetting and arraysetting.items not being populated - Changed plugin/theme event emitters to AsyncEventEmitter --- client/src/modules/extmodule.js | 22 +--------- client/src/modules/plugin.js | 42 ++----------------- client/src/modules/theme.js | 35 ++-------------- client/src/structs/settings/settingsset.js | 13 +----- client/src/structs/settings/types/array.js | 25 ++++++++++- .../src/structs/settings/types/basesetting.js | 6 +-- 6 files changed, 36 insertions(+), 107 deletions(-) diff --git a/client/src/modules/extmodule.js b/client/src/modules/extmodule.js index 66fbfafd..43f37811 100644 --- a/client/src/modules/extmodule.js +++ b/client/src/modules/extmodule.js @@ -8,27 +8,9 @@ * LICENSE file in the root directory of this source tree. */ +import { AsyncEventEmitter } from 'common'; import { EventEmitter } from 'events'; -class ExtModuleEvents { - constructor(extmodule) { - this.extmodule = extmodule; - this.emitter = new EventEmitter(); - } - - on(eventname, callback) { - this.emitter.on(eventname, callback); - } - - off(eventname, callback) { - this.emitter.removeListener(eventname, callback); - } - - emit(...args) { - this.emitter.emit(...args); - } -} - export default class ExtModule { constructor(pluginInternals) { @@ -57,6 +39,6 @@ export default class ExtModule { get enabled() { return true } get config() { return this.userConfig.config || [] } get data() { return this.userConfig.data || (this.userConfig.data = {}) } - get events() { return this.EventEmitter ? this.EventEmitter : (this.EventEmitter = new ExtModuleEvents(this)) } + get events() { return this.EventEmitter ? this.EventEmitter : (this.EventEmitter = new AsyncEventEmitter()) } } diff --git a/client/src/modules/plugin.js b/client/src/modules/plugin.js index f3e2efb0..889e2b4d 100644 --- a/client/src/modules/plugin.js +++ b/client/src/modules/plugin.js @@ -8,36 +8,17 @@ * LICENSE file in the root directory of this source tree. */ -import { Utils, FileUtils } from 'common'; +import { Utils, FileUtils, AsyncEventEmitter } from 'common'; import { Modals } from 'ui'; import { EventEmitter } from 'events'; import PluginManager from './pluginmanager'; import { SettingUpdatedEvent, SettingsUpdatedEvent } from 'structs'; -class PluginEvents { - constructor(plugin) { - this.plugin = plugin; - this.emitter = new EventEmitter(); - } - - on(eventname, callback) { - this.emitter.on(eventname, callback); - } - - off(eventname, callback) { - this.emitter.removeListener(eventname, callback); - } - - emit(...args) { - this.emitter.emit(...args); - } -} - export default class Plugin { constructor(pluginInternals) { this.__pluginInternals = pluginInternals; - this.saveSettings = this.saveSettings.bind(this); + this.saveConfiguration = this.saveConfiguration.bind(this); this.hasSettings = this.config && this.config.length > 0; this.start = this.start.bind(this); this.stop = this.stop.bind(this); @@ -70,29 +51,12 @@ export default class Plugin { get pluginConfig() { return this.config } get data() { return this.userConfig.data || (this.userConfig.data = {}) } get exports() { return this._exports ? this._exports : (this._exports = this.getExports()) } - get events() { return this.EventEmitter ? this.EventEmitter : (this.EventEmitter = new PluginEvents(this)) } - - getSetting(setting_id, category_id) { - for (let category of this.config) { - if (category_id && category.category !== category_id) continue; - for (let setting of category.settings) { - if (setting.id !== setting_id) continue; - return setting.value; - } - } - } + get events() { return this.EventEmitter ? this.EventEmitter : (this.EventEmitter = new AsyncEventEmitter()) } showSettingsModal() { return Modals.contentSettings(this); } - async saveSettings(newSettings) { - const updatedSettings = this.settings.merge(newSettings); - - await this.saveConfiguration(); - return updatedSettings; - } - async saveConfiguration() { try { await FileUtils.writeFile(`${this.pluginPath}/user.config.json`, JSON.stringify({ diff --git a/client/src/modules/theme.js b/client/src/modules/theme.js index 9d1bf496..da96e5ae 100644 --- a/client/src/modules/theme.js +++ b/client/src/modules/theme.js @@ -13,34 +13,15 @@ import ThemeManager from './thememanager'; import { EventEmitter } from 'events'; import { SettingUpdatedEvent, SettingsUpdatedEvent } from 'structs'; import { DOM, Modals } from 'ui'; -import { Utils, FileUtils, ClientIPC, ClientLogger as Logger } from 'common'; +import { Utils, FileUtils, ClientIPC, ClientLogger as Logger, AsyncEventEmitter } from 'common'; import filewatcher from 'filewatcher'; -class ThemeEvents { - constructor(theme) { - this.theme = theme; - this.emitter = new EventEmitter(); - } - - on(eventname, callback) { - this.emitter.on(eventname, callback); - } - - off(eventname, callback) { - this.emitter.removeListener(eventname, callback); - } - - emit(...args) { - this.emitter.emit(...args); - } -} - export default class Theme { constructor(themeInternals) { this.__themeInternals = themeInternals; this.hasSettings = this.config && this.config.length > 0; - this.saveSettings = this.saveSettings.bind(this); + this.saveConfiguration = this.saveConfiguration.bind(this); this.enable = this.enable.bind(this); this.disable = this.disable.bind(this); @@ -79,22 +60,12 @@ export default class Theme { get themeConfig() { return this.config } get data() { return this.userConfig.data || (this.userConfig.data = {}) } get css() { return this.data.css } - get events() { return this.EventEmitter ? this.EventEmitter : (this.EventEmitter = new ThemeEvents(this)) } + get events() { return this.EventEmitter ? this.EventEmitter : (this.EventEmitter = new AsyncEventEmitter()) } showSettingsModal() { return Modals.contentSettings(this); } - async saveSettings(newSettings) { - const updatedSettings = this.settings.merge(newSettings); - - // As the theme's configuration has changed it needs recompiling - // When the compiled CSS has been saved it will also save the configuration - await this.recompile(); - - return this.settingsUpdated(updatedSettings); - } - async saveConfiguration() { try { await FileUtils.writeFile(`${this.themePath}/user.config.json`, JSON.stringify({ diff --git a/client/src/structs/settings/settingsset.js b/client/src/structs/settings/settingsset.js index a40921b1..e488f6ef 100644 --- a/client/src/structs/settings/settingsset.js +++ b/client/src/structs/settings/settingsset.js @@ -101,17 +101,6 @@ export default class SettingsSet { return false; } - /** - * Return the first setting that matches the id in any category - */ - findFirst(settingId) { - for (let cat of this.categories) { - const found = cat.settings.find(s => s.id === settingId); - if (found) return found; - } - return null; - } - /** * Returns the first category where calling {function} returns true. * @param {Function} function A function to call to filter categories @@ -146,7 +135,7 @@ export default class SettingsSet { */ findSetting(f) { for (let category of this.categories) { - const setting = category.findSetting(f); + const setting = category.find(f); if (setting) return setting; } } diff --git a/client/src/structs/settings/types/array.js b/client/src/structs/settings/types/array.js index 55744da5..023fc69a 100644 --- a/client/src/structs/settings/types/array.js +++ b/client/src/structs/settings/types/array.js @@ -24,7 +24,12 @@ export default class ArraySetting extends Setting { this.args.schemes = this.schemes.map(scheme => new SettingsScheme(scheme)); this.args.items = this.value ? this.value.map(item => this.createItem(item.args || item)) : []; - this.updateValue(false, false); + this.args.value = this.items.map(item => { + if (!item) return; + item.setSaved(); + return item.strip(); + }); + this.changed = !Utils.compare(this.args.value, this.args.saved_value); } /** @@ -142,6 +147,24 @@ export default class ArraySetting extends Setting { return set; } + /** + * Merges a setting into this setting without emitting events (and therefore synchronously). + * This only exists for use by the constructor and SettingsCategory. + */ + _merge(newSetting) { + const value = newSetting.args ? newSetting.args.value : newSetting.value; + const old_value = this.args.value; + if (Utils.compare(value, old_value)) return []; + this.args.value = value; + this.args.items = this.value ? this.value.map(item => this.createItem(item.args || item)) : []; + this.changed = !Utils.compare(this.args.value, this.args.saved_value); + + return [{ + setting: this, setting_id: this.id, + value, old_value + }]; + } + /** * Sets the value of this setting. * This is only intended for use by settings. diff --git a/client/src/structs/settings/types/basesetting.js b/client/src/structs/settings/types/basesetting.js index 81271bef..4c45197c 100644 --- a/client/src/structs/settings/types/basesetting.js +++ b/client/src/structs/settings/types/basesetting.js @@ -156,7 +156,7 @@ export default class Setting { * @param {Boolean} emit Whether to emit a SettingUpdatedEvent * @return {Promise} */ - setValue(value, emit_multi = true, emit = true) { + async setValue(value, emit_multi = true, emit = true) { const old_value = this.args.value; if (Utils.compare(value, old_value)) return []; this.args.value = value; @@ -168,10 +168,10 @@ export default class Setting { }; if (emit) - this.emit('setting-updated', new SettingUpdatedEvent(updatedSetting)); + await this.emit('setting-updated', new SettingUpdatedEvent(updatedSetting)); if (emit_multi) - this.emit('settings-updated', new SettingsUpdatedEvent({ + await this.emit('settings-updated', new SettingsUpdatedEvent({ updatedSettings: [updatedSetting] }));