Add live updating settings sets and categories

This commit is contained in:
Samuel Elliott 2018-03-06 00:47:34 +00:00
parent 3ab4fd8a9a
commit da5e0ac99c
No known key found for this signature in database
GPG Key ID: 8420C7CDE43DC4D6
3 changed files with 170 additions and 23 deletions

View File

@ -9,9 +9,12 @@
*/
import Setting from './setting';
import BaseSetting from './types/basesetting';
import { ClientLogger as Logger, AsyncEventEmitter } from 'common';
import { SettingUpdatedEvent, SettingsUpdatedEvent } from 'structs';
let instances = 0;
export default class SettingsCategory {
constructor(args, ...merge) {
@ -24,17 +27,10 @@ export default class SettingsCategory {
this._merge(newCategory);
}
this._eventsKey = instances++;
for (let setting of this.settings) {
setting.on('setting-updated', ({ value, old_value }) => this.emit('setting-updated', new SettingUpdatedEvent({
category: this, category_id: this.id,
setting, setting_id: setting.id,
value, old_value
})));
setting.on('settings-updated', ({ updatedSettings }) => this.emit('settings-updated', new SettingsUpdatedEvent({
updatedSettings: updatedSettings.map(updatedSetting => new SettingUpdatedEvent(Object.assign({
category: this, category_id: this.id
}, updatedSetting)))
})));
this._bindSettingEvents(setting);
}
}
@ -83,6 +79,77 @@ export default class SettingsCategory {
return false;
}
/**
* Binds events to a category.
* This only exists for use by the constructor and settingsset.addCategory.
*/
_bindSettingEvents(setting) {
setting.on('setting-updated', setting[this._eventsKey + '_settingscategory_event_setting-updated'] = ({ value, old_value }) => this.emit('setting-updated', new SettingUpdatedEvent({
category: this, category_id: this.id,
setting, setting_id: setting.id,
value, old_value
})));
setting.on('settings-updated', setting[this._eventsKey + '_settingscategory_event_settings-updated'] = ({ updatedSettings }) => this.emit('settings-updated', new SettingsUpdatedEvent({
updatedSettings: updatedSettings.map(updatedSetting => new SettingUpdatedEvent(Object.assign({
category: this, category_id: this.id
}, updatedSetting)))
})));
}
/**
* Dynamically adds a setting to this category.
* @param {Setting} category The setting to add to this category
* @param {Number} index The index to add the setting at (optional)
* @return {Promise}
*/
async addSetting(setting, index) {
if (this.settings.find(s => s === setting)) return;
if (!(setting instanceof BaseSetting))
setting = new Setting(setting);
if (this.getSetting(setting.id))
throw {message: 'A setting with this ID already exists.'};
this._bindSettingEvents(setting);
if (index === undefined) index = this.settings.length;
this.settings.splice(index, 0, setting);
const event = {
category, category_id: category.id,
setting, setting_id: setting.id,
at_index: index
};
await setting.emit('added-to', event);
await this.emit('added-setting', event);
return setting;
}
/**
* Dynamically removes a setting from this category.
* @param {Setting} setting The setting to remove from this category
* @return {Promise}
*/
async removeSetting(setting) {
setting.off('setting-updated', setting[this._eventsKey + '_settingscategory_event_setting-updated']);
setting.off('settings-updated', setting[this._eventsKey + '_settingscategory_event_settings-updated']);
let index;
while ((index = this.settings.findIndex(c => c === category)) > -1) {
this.settings.splice(index, 0);
}
const event = {
set: this, set_id: this.id,
category, category_id: category.id,
from_index: index
};
await category.emit('removed-from', event);
await this.emit('removed-category', event);
}
/**
* Returns the first setting where calling {function} returns true.
* @param {Function} function A function to call to filter settings
@ -107,7 +174,7 @@ export default class SettingsCategory {
* @return {Setting}
*/
getSetting(id) {
return this.findSetting(setting => setting.id === id);
return this.find(setting => setting.id === id);
}
/**

View File

@ -14,6 +14,8 @@ import { ClientLogger as Logger, AsyncEventEmitter } from 'common';
import { SettingUpdatedEvent, SettingsUpdatedEvent } from 'structs';
import { Modals } from 'ui';
let instances = 0;
export default class SettingsSet {
constructor(args, ...merge) {
@ -27,18 +29,10 @@ export default class SettingsSet {
this._merge(newSet);
}
this._eventsKey = instances++;
for (let category of this.categories) {
category.on('setting-updated', ({ setting, value, old_value }) => this.emit('setting-updated', new SettingUpdatedEvent({
set: this, set_id: this.id,
category, category_id: category.id,
setting, setting_id: setting.id,
value, old_value
})));
category.on('settings-updated', ({ updatedSettings }) => this.emit('settings-updated', new SettingsUpdatedEvent({
updatedSettings: updatedSettings.map(updatedSetting => new SettingUpdatedEvent(Object.assign({
set: this, set_id: this.id
}, updatedSetting)))
})));
this._bindCategoryEvents(category);
}
}
@ -101,6 +95,92 @@ export default class SettingsSet {
return false;
}
/**
* Binds events to a category.
* This only exists for use by the constructor and settingsset.addCategory.
*/
_bindCategoryEvents(category) {
category.on('setting-updated', category[this._eventsKey + '_settingsset_event_setting-updated'] = ({ setting, value, old_value }) => this.emit('setting-updated', new SettingUpdatedEvent({
set: this, set_id: this.id,
category, category_id: category.id,
setting, setting_id: setting.id,
value, old_value
})));
category.on('settings-updated', category[this._eventsKey + '_settingsset_event_settings-updated'] = ({ updatedSettings }) => this.emit('settings-updated', new SettingsUpdatedEvent({
updatedSettings: updatedSettings.map(updatedSetting => new SettingUpdatedEvent(Object.assign({
set: this, set_id: this.id
}, updatedSetting)))
})));
category.on('added-setting', category[this._eventsKey + '_settingsset_event_added-setting'] = ({ setting, at_index }) => this.emit('added-setting', {
set: this, set_id: this.id,
category, category_id: category.id,
setting, setting_id: setting.id,
at_index
}));
category.on('removed-setting', category[this._eventsKey + '_settingsset_event_removed-setting'] = ({ setting, from_index }) => this.emit('removed-setting', {
set: this, set_id: this.id,
category, category_id: category.id,
setting, setting_id: setting.id,
from_index
}));
}
/**
* Dynamically adds a category to this set.
* @param {SettingsCategory} category The category to add to this set
* @param {Number} index The index to add the category at (optional)
* @return {Promise}
*/
async addCategory(category, index) {
if (this.categories.find(c => c === category)) return;
if (!(category instanceof SettingsCategory))
category = new SettingsCategory(category);
if (this.getCategory(category.id))
throw {message: 'A category with this ID already exists.'};
this._bindCategoryEvents(category);
if (index === undefined) index = this.categories.length;
this.categories.splice(index, 0, category);
const event = {
set: this, set_id: this.id,
category, category_id: category.id,
at_index: index
};
await category.emit('added-to', event);
await this.emit('added-category', event);
return category;
}
/**
* Dynamically removes a category from this set.
* @param {SettingsCategory} category The category to remove from this set
* @return {Promise}
*/
async removeCategory(category) {
category.off('setting-updated', category[this._eventsKey + '_settingsset_event_setting-updated']);
category.off('settings-updated', category[this._eventsKey + '_settingsset_event_settings-updated']);
category.off('added-setting', category[this._eventsKey + '_settingsset_event_added-setting']);
category.off('removed-setting', category[this._eventsKey + '_settingsset_event_removed-setting']);
let index;
while ((index = this.categories.findIndex(c => c === category)) > -1) {
this.categories.splice(index, 0);
}
const event = {
set: this, set_id: this.id,
category, category_id: category.id,
from_index: index
};
await category.emit('removed-from', event);
await this.emit('removed-category', event);
}
/**
* Returns the first category where calling {function} returns true.
* @param {Function} function A function to call to filter categories

View File

@ -8,7 +8,7 @@
* LICENSE file in the root directory of this source tree.
*/
import { Utils, FileUtils, AsyncEventEmitter } from 'common';
import { Utils, FileUtils, ClientLogger as Logger, AsyncEventEmitter } from 'common';
import { Settings, Events, PluginManager, ThemeManager } from 'modules';
import BaseModal from './components/common/Modal.vue';
import BasicModal from './components/bd/modals/BasicModal.vue';