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 SettingsCategory from '../settingscategory';
|
||||
import SettingsScheme from '../settingsscheme';
|
||||
import { SettingsUpdatedEvent } from 'structs';
|
||||
|
||||
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)
|
||||
* @return {SettingsSet} The new set
|
||||
*/
|
||||
addItem(item) {
|
||||
const newItem = this.createItem(item);
|
||||
this.args.items.push(newItem);
|
||||
this.updateValue();
|
||||
return newItem;
|
||||
async addItem(_item) {
|
||||
const item = this.createItem(_item);
|
||||
this.args.items.push(item);
|
||||
await this.updateValue();
|
||||
|
||||
await this.emit('item-added', { item });
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a set from this array setting.
|
||||
* This ignores the minimum value.
|
||||
* @param {SettingsSet} item The set to remove
|
||||
* @return {Promise}
|
||||
*/
|
||||
removeItem(item) {
|
||||
async removeItem(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;
|
||||
|
||||
const set = new SettingsSet({
|
||||
id: item ? item.args ? item.args.id : item.id : Math.random(),
|
||||
settings: Utils.deepclone(this.settings),
|
||||
schemes: this.schemes
|
||||
}, item ? item.args || item : undefined);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* This can be overridden by other settings types.
|
||||
* @param {SettingUpdatedEvent} updatedSetting
|
||||
*/
|
||||
setValueHook(updatedSetting) {
|
||||
this.args.items = updatedSetting.value ? updatedSetting.value.map(item => this.createItem(item)) : [];
|
||||
async setValueHook(updatedSetting) {
|
||||
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.
|
||||
* 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).
|
||||
* 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;
|
||||
return this._setValue(value);
|
||||
return this._setValue(value, hook);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,12 +116,13 @@ export default class Setting {
|
|||
* @return {Promise}
|
||||
*/
|
||||
async merge(newSetting, emit_multi = true, emit = true) {
|
||||
const updatedSettings = this._merge(newSetting);
|
||||
const updatedSettings = this._merge(newSetting, false);
|
||||
if (!updatedSettings.length) return [];
|
||||
const updatedSetting = updatedSettings[0];
|
||||
|
||||
await this.setValueHook(updatedSettings[0]);
|
||||
|
||||
if (emit)
|
||||
await this.emit('setting-updated', updatedSetting);
|
||||
await this.emit('setting-updated', updatedSettings[0]);
|
||||
|
||||
if (emit_multi)
|
||||
await this.emit('settings-updated', new SettingsUpdatedEvent({
|
||||
|
@ -135,7 +136,7 @@ export default class Setting {
|
|||
* Sets the value of this setting.
|
||||
* This only exists for use by the constructor and SettingsCategory.
|
||||
*/
|
||||
_setValue(value) {
|
||||
_setValue(value, hook = true) {
|
||||
const old_value = this.args.value;
|
||||
if (Utils.compare(value, old_value)) return [];
|
||||
this.args.value = value;
|
||||
|
@ -146,7 +147,8 @@ export default class Setting {
|
|||
value, old_value
|
||||
});
|
||||
|
||||
this.setValueHook(updatedSetting);
|
||||
if (hook)
|
||||
this.setValueHookSync(updatedSetting);
|
||||
|
||||
return [updatedSetting];
|
||||
}
|
||||
|
@ -156,7 +158,8 @@ export default class Setting {
|
|||
* This can be overridden by other settings types.
|
||||
* @param {SettingUpdatedEvent} updatedSetting
|
||||
*/
|
||||
setValueHook(updatedSetting) {}
|
||||
async setValueHook(updatedSetting) {}
|
||||
setValueHookSync(updatedSetting) {}
|
||||
|
||||
/**
|
||||
* Sets the value of this setting.
|
||||
|
@ -164,9 +167,11 @@ export default class Setting {
|
|||
* @return {Promise}
|
||||
*/
|
||||
async setValue(value, emit_multi = true, emit = true) {
|
||||
const updatedSettings = this._setValue(value);
|
||||
const updatedSettings = this._setValue(value, false);
|
||||
if (!updatedSettings.length) return [];
|
||||
|
||||
await this.setValueHook(updatedSettings[0]);
|
||||
|
||||
if (emit)
|
||||
await this.emit('setting-updated', updatedSettings[0]);
|
||||
|
||||
|
|
|
@ -48,14 +48,14 @@
|
|||
MiSettings, MiOpenInNew, MiMinus
|
||||
},
|
||||
methods: {
|
||||
addItem(openModal) {
|
||||
async addItem(openModal) {
|
||||
if (this.setting.disabled || this.setting.max && this.setting.items.length >= this.setting.max) return;
|
||||
const item = this.setting.addItem();
|
||||
if (openModal) this.showModal(item, this.setting.items.length);
|
||||
const item = await this.setting.addItem();
|
||||
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;
|
||||
this.setting.removeItem(item);
|
||||
await this.setting.removeItem(item);
|
||||
},
|
||||
showModal(item, index) {
|
||||
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);
|
||||
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 => {
|
||||
console.log('Received plugin setting update:', event);
|
||||
});
|
||||
|
@ -92,14 +92,14 @@ module.exports = (Plugin, Api, Vendor, Dependencies) => {
|
|||
test1() { return 'It works!'; }
|
||||
test2() { return 'This works too!'; }
|
||||
|
||||
settingChanged(category, setting_id, value) {
|
||||
settingChanged(event) {
|
||||
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;
|
||||
Logger.log([ 'Settings updated', settings ]);
|
||||
Logger.log([ 'Settings updated', event.updatedSettings ]);
|
||||
}
|
||||
|
||||
get settingscomponent() {
|
||||
|
|
Loading…
Reference in New Issue