Better merging of array setting items
This commit is contained in:
parent
da5e0ac99c
commit
72dd93503a
|
@ -14,6 +14,7 @@ import Setting from './basesetting';
|
||||||
import SettingsSet from '../settingsset';
|
import SettingsSet from '../settingsset';
|
||||||
import SettingsCategory from '../settingscategory';
|
import SettingsCategory from '../settingscategory';
|
||||||
import SettingsScheme from '../settingsscheme';
|
import SettingsScheme from '../settingsscheme';
|
||||||
|
import { SettingsUpdatedEvent } from 'structs';
|
||||||
|
|
||||||
export default class ArraySetting extends Setting {
|
export default class ArraySetting extends Setting {
|
||||||
|
|
||||||
|
@ -108,21 +109,27 @@ export default class ArraySetting extends Setting {
|
||||||
* @param {SettingsSet} item Values to merge into the new set (optional)
|
* @param {SettingsSet} item Values to merge into the new set (optional)
|
||||||
* @return {SettingsSet} The new set
|
* @return {SettingsSet} The new set
|
||||||
*/
|
*/
|
||||||
addItem(item) {
|
async addItem(_item) {
|
||||||
const newItem = this.createItem(item);
|
const item = this.createItem(_item);
|
||||||
this.args.items.push(newItem);
|
this.args.items.push(item);
|
||||||
this.updateValue();
|
await this.updateValue();
|
||||||
return newItem;
|
|
||||||
|
await this.emit('item-added', { item });
|
||||||
|
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a set from this array setting.
|
* Removes a set from this array setting.
|
||||||
* This ignores the minimum value.
|
* This ignores the minimum value.
|
||||||
* @param {SettingsSet} item The set to remove
|
* @param {SettingsSet} item The set to remove
|
||||||
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
removeItem(item) {
|
async removeItem(item) {
|
||||||
this.args.items = this.items.filter(i => i !== item);
|
this.args.items = this.items.filter(i => i !== item);
|
||||||
this.updateValue();
|
await this.updateValue();
|
||||||
|
|
||||||
|
await this.emit('item-removed', { item });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -135,24 +142,84 @@ export default class ArraySetting extends Setting {
|
||||||
return item;
|
return item;
|
||||||
|
|
||||||
const set = new SettingsSet({
|
const set = new SettingsSet({
|
||||||
|
id: item ? item.args ? item.args.id : item.id : Math.random(),
|
||||||
settings: Utils.deepclone(this.settings),
|
settings: Utils.deepclone(this.settings),
|
||||||
schemes: this.schemes
|
schemes: this.schemes
|
||||||
}, item ? item.args || item : undefined);
|
}, item ? item.args || item : undefined);
|
||||||
|
|
||||||
set.setSaved();
|
set.setSaved();
|
||||||
set.on('settings-updated', () => this.updateValue());
|
set.on('settings-updated', async event => {
|
||||||
|
await this.emit('item-updated', { item: set, event, updatedSettings: event.updatedSettings });
|
||||||
|
if (event.args.updating_array !== this) await this.updateValue();
|
||||||
|
});
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to be called after the value changes.
|
||||||
|
* This can be overridden by other settings types.
|
||||||
|
* This function is used when the value needs to be updated synchronously (basically just in the constructor - so there won't be any events to emit anyway).
|
||||||
|
* @param {SettingUpdatedEvent} updatedSetting
|
||||||
|
*/
|
||||||
|
setValueHookSync(updatedSetting) {
|
||||||
|
this.args.items = updatedSetting.value ? updatedSetting.value.map(item => this.createItem(item)) : [];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to be called after the value changes.
|
* Function to be called after the value changes.
|
||||||
* This can be overridden by other settings types.
|
* This can be overridden by other settings types.
|
||||||
* @param {SettingUpdatedEvent} updatedSetting
|
* @param {SettingUpdatedEvent} updatedSetting
|
||||||
*/
|
*/
|
||||||
setValueHook(updatedSetting) {
|
async setValueHook(updatedSetting) {
|
||||||
this.args.items = updatedSetting.value ? updatedSetting.value.map(item => this.createItem(item)) : [];
|
const newItems = [];
|
||||||
|
let error;
|
||||||
|
|
||||||
|
for (let newItem of updatedSetting.value) {
|
||||||
|
try {
|
||||||
|
const item = this.items.find(i => i.id && i.id === newItem.id);
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
// Merge the new item into the original item
|
||||||
|
newItems.push(item);
|
||||||
|
const updatedSettings = await item.merge(newItem, false);
|
||||||
|
if (!updatedSettings.length) continue;
|
||||||
|
|
||||||
|
const event = new SettingsUpdatedEvent({
|
||||||
|
updatedSettings,
|
||||||
|
updating_array: this
|
||||||
|
});
|
||||||
|
|
||||||
|
await item.emit('settings-updated', event);
|
||||||
|
// await this.emit('item-updated', { item, event, updatedSettings });
|
||||||
|
} else {
|
||||||
|
// Add a new item
|
||||||
|
const item = this.createItem(newItem);
|
||||||
|
newItems.push(item);
|
||||||
|
await this.emit('item-added', { item });
|
||||||
|
}
|
||||||
|
} catch (e) { error = e; }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let item of this.items) {
|
||||||
|
if (newItems.includes(item)) continue;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Item removed
|
||||||
|
await this.emit('item-removed', { item });
|
||||||
|
} catch (e) { error = e; }
|
||||||
|
}
|
||||||
|
|
||||||
|
this.args.items = newItems;
|
||||||
|
|
||||||
|
// We can't throw anything before the items array is updated, otherwise the array setting would be in an inconsistent state where the values in this.items wouldn't match the values in this.value
|
||||||
|
if (error) throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// emit(...args) {
|
||||||
|
// console.log('Emitting event', args[0], 'with data', args[1]);
|
||||||
|
// return this.emitter.emit(...args);
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the value of this array setting.
|
* Updates the value of this array setting.
|
||||||
* This only exists for use by array settings.
|
* This only exists for use by array settings.
|
||||||
|
|
|
@ -105,9 +105,9 @@ export default class Setting {
|
||||||
* Merges a setting into this setting without emitting events (and therefore synchronously).
|
* Merges a setting into this setting without emitting events (and therefore synchronously).
|
||||||
* This only exists for use by the constructor and SettingsCategory.
|
* This only exists for use by the constructor and SettingsCategory.
|
||||||
*/
|
*/
|
||||||
_merge(newSetting) {
|
_merge(newSetting, hook = true) {
|
||||||
const value = newSetting.args ? newSetting.args.value : newSetting.value;
|
const value = newSetting.args ? newSetting.args.value : newSetting.value;
|
||||||
return this._setValue(value);
|
return this._setValue(value, hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -116,12 +116,13 @@ export default class Setting {
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
async merge(newSetting, emit_multi = true, emit = true) {
|
async merge(newSetting, emit_multi = true, emit = true) {
|
||||||
const updatedSettings = this._merge(newSetting);
|
const updatedSettings = this._merge(newSetting, false);
|
||||||
if (!updatedSettings.length) return [];
|
if (!updatedSettings.length) return [];
|
||||||
const updatedSetting = updatedSettings[0];
|
|
||||||
|
await this.setValueHook(updatedSettings[0]);
|
||||||
|
|
||||||
if (emit)
|
if (emit)
|
||||||
await this.emit('setting-updated', updatedSetting);
|
await this.emit('setting-updated', updatedSettings[0]);
|
||||||
|
|
||||||
if (emit_multi)
|
if (emit_multi)
|
||||||
await this.emit('settings-updated', new SettingsUpdatedEvent({
|
await this.emit('settings-updated', new SettingsUpdatedEvent({
|
||||||
|
@ -135,7 +136,7 @@ export default class Setting {
|
||||||
* Sets the value of this setting.
|
* Sets the value of this setting.
|
||||||
* This only exists for use by the constructor and SettingsCategory.
|
* This only exists for use by the constructor and SettingsCategory.
|
||||||
*/
|
*/
|
||||||
_setValue(value) {
|
_setValue(value, hook = true) {
|
||||||
const old_value = this.args.value;
|
const old_value = this.args.value;
|
||||||
if (Utils.compare(value, old_value)) return [];
|
if (Utils.compare(value, old_value)) return [];
|
||||||
this.args.value = value;
|
this.args.value = value;
|
||||||
|
@ -146,7 +147,8 @@ export default class Setting {
|
||||||
value, old_value
|
value, old_value
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setValueHook(updatedSetting);
|
if (hook)
|
||||||
|
this.setValueHookSync(updatedSetting);
|
||||||
|
|
||||||
return [updatedSetting];
|
return [updatedSetting];
|
||||||
}
|
}
|
||||||
|
@ -156,7 +158,8 @@ export default class Setting {
|
||||||
* This can be overridden by other settings types.
|
* This can be overridden by other settings types.
|
||||||
* @param {SettingUpdatedEvent} updatedSetting
|
* @param {SettingUpdatedEvent} updatedSetting
|
||||||
*/
|
*/
|
||||||
setValueHook(updatedSetting) {}
|
async setValueHook(updatedSetting) {}
|
||||||
|
setValueHookSync(updatedSetting) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of this setting.
|
* Sets the value of this setting.
|
||||||
|
@ -164,9 +167,11 @@ export default class Setting {
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
async setValue(value, emit_multi = true, emit = true) {
|
async setValue(value, emit_multi = true, emit = true) {
|
||||||
const updatedSettings = this._setValue(value);
|
const updatedSettings = this._setValue(value, false);
|
||||||
if (!updatedSettings.length) return [];
|
if (!updatedSettings.length) return [];
|
||||||
|
|
||||||
|
await this.setValueHook(updatedSettings[0]);
|
||||||
|
|
||||||
if (emit)
|
if (emit)
|
||||||
await this.emit('setting-updated', updatedSettings[0]);
|
await this.emit('setting-updated', updatedSettings[0]);
|
||||||
|
|
||||||
|
|
|
@ -48,14 +48,14 @@
|
||||||
MiSettings, MiOpenInNew, MiMinus
|
MiSettings, MiOpenInNew, MiMinus
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addItem(openModal) {
|
async addItem(openModal) {
|
||||||
if (this.setting.disabled || this.setting.max && this.setting.items.length >= this.setting.max) return;
|
if (this.setting.disabled || this.setting.max && this.setting.items.length >= this.setting.max) return;
|
||||||
const item = this.setting.addItem();
|
const item = await this.setting.addItem();
|
||||||
if (openModal) this.showModal(item, this.setting.items.length);
|
if (openModal) this.showModal(item, this.setting.items.length - 1);
|
||||||
},
|
},
|
||||||
removeItem(item) {
|
async removeItem(item) {
|
||||||
if (this.setting.disabled || this.setting.min && this.setting.items.length <= this.setting.min) return;
|
if (this.setting.disabled || this.setting.min && this.setting.items.length <= this.setting.min) return;
|
||||||
this.setting.removeItem(item);
|
await this.setting.removeItem(item);
|
||||||
},
|
},
|
||||||
showModal(item, index) {
|
showModal(item, index) {
|
||||||
Modals.settings(item, this.setting.headertext ? this.setting.headertext.replace(/%n/, index + 1) : this.setting.text + ` #${index + 1}`);
|
Modals.settings(item, this.setting.headertext ? this.setting.headertext.replace(/%n/, index + 1) : this.setting.text + ` #${index + 1}`);
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"id": "example-plugin-4",
|
||||||
|
"name": "Example Plugin 4",
|
||||||
|
"authors": [
|
||||||
|
"Samuel Elliott"
|
||||||
|
],
|
||||||
|
"version": 1.0,
|
||||||
|
"description": "Plugin for testing array setting events as the first example plugin has a lot of stuff in it now."
|
||||||
|
},
|
||||||
|
"main": "index.js",
|
||||||
|
"type": "plugin",
|
||||||
|
"defaultConfig": [
|
||||||
|
{
|
||||||
|
"category": "default",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"id": "array-1",
|
||||||
|
"type": "array",
|
||||||
|
"text": "Test settings array",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"category": "default",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"id": "default-0",
|
||||||
|
"type": "bool",
|
||||||
|
"value": false,
|
||||||
|
"text": "Bool Test Setting 3",
|
||||||
|
"hint": "Bool Test Setting Hint 3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "default-1",
|
||||||
|
"type": "text",
|
||||||
|
"value": "defaultValue",
|
||||||
|
"text": "Text Test Setting",
|
||||||
|
"hint": "Text Test Setting Hint"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schemes": [
|
||||||
|
{
|
||||||
|
"id": "scheme-1",
|
||||||
|
"name": "Test scheme",
|
||||||
|
"icon_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Cow_female_black_white.jpg/220px-Cow_female_black_white.jpg",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"category": "default",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"id": "default-0",
|
||||||
|
"value": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "scheme-2",
|
||||||
|
"name": "Another test scheme",
|
||||||
|
"icon_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Cow_female_black_white.jpg/220px-Cow_female_black_white.jpg",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"category": "default",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"id": "default-0",
|
||||||
|
"value": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "default-1",
|
||||||
|
"value": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Cow_female_black_white.jpg/220px-Cow_female_black_white.jpg"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
module.exports = (Plugin, { Logger }) => class extends Plugin {
|
||||||
|
onstart() {
|
||||||
|
// Some array event examples
|
||||||
|
const arraySetting = this.settings.getSetting('default', 'array-1');
|
||||||
|
Logger.log('Array setting', arraySetting);
|
||||||
|
arraySetting.on('item-added', event => Logger.log('Item', event.item, 'was added to the array setting'));
|
||||||
|
arraySetting.on('item-updated', event => Logger.log('Item', event.item, 'of the array setting was updated', event));
|
||||||
|
arraySetting.on('item-removed', event => Logger.log('Item', event.item, 'removed from the array setting'));
|
||||||
|
}
|
||||||
|
};
|
|
@ -14,7 +14,7 @@ module.exports = (Plugin, Api, Vendor, Dependencies) => {
|
||||||
Events.subscribe('TEST_EVENT', this.eventTest);
|
Events.subscribe('TEST_EVENT', this.eventTest);
|
||||||
Logger.log('onStart');
|
Logger.log('onStart');
|
||||||
|
|
||||||
Logger.log(`Plugin setting "default-0" value: ${this.getSetting('default-0')}`);
|
Logger.log(`Plugin setting "default-0" value: ${this.settings.get('default-0')}`);
|
||||||
this.events.on('setting-updated', event => {
|
this.events.on('setting-updated', event => {
|
||||||
console.log('Received plugin setting update:', event);
|
console.log('Received plugin setting update:', event);
|
||||||
});
|
});
|
||||||
|
@ -92,14 +92,14 @@ module.exports = (Plugin, Api, Vendor, Dependencies) => {
|
||||||
test1() { return 'It works!'; }
|
test1() { return 'It works!'; }
|
||||||
test2() { return 'This works too!'; }
|
test2() { return 'This works too!'; }
|
||||||
|
|
||||||
settingChanged(category, setting_id, value) {
|
settingChanged(event) {
|
||||||
if (!this.enabled) return;
|
if (!this.enabled) return;
|
||||||
Logger.log(`${category}/${setting_id} changed to ${value}`);
|
Logger.log(`${event.category_id}/${event.setting_id} changed to ${event.value}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsChanged(settings) {
|
settingsChanged(event) {
|
||||||
if (!this.enabled) return;
|
if (!this.enabled) return;
|
||||||
Logger.log([ 'Settings updated', settings ]);
|
Logger.log([ 'Settings updated', event.updatedSettings ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
get settingscomponent() {
|
get settingscomponent() {
|
||||||
|
|
Loading…
Reference in New Issue