You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
6.1 KiB
225 lines
6.1 KiB
/* typehints:start */
|
|
import { Application } from "../application";
|
|
/* typehints:end */
|
|
|
|
import { createLogger } from "../core/logging";
|
|
import { T } from "../translations";
|
|
|
|
const logger = createLogger("setting_types");
|
|
|
|
const standaloneOnlySettingHtml = `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`;
|
|
|
|
export class BaseSetting {
|
|
/**
|
|
*
|
|
* @param {string} id
|
|
* @param {string} categoryId
|
|
* @param {function(Application, any):void} changeCb
|
|
* @param {boolean} enabled
|
|
*/
|
|
constructor(id, categoryId, changeCb, enabled) {
|
|
this.id = id;
|
|
this.categoryId = categoryId;
|
|
this.changeCb = changeCb;
|
|
this.enabled = enabled;
|
|
|
|
/** @type {Application} */
|
|
this.app = null;
|
|
|
|
this.element = null;
|
|
this.dialogs = null;
|
|
}
|
|
|
|
/**
|
|
* @param {Application} app
|
|
* @param {any} value
|
|
*/
|
|
apply(app, value) {
|
|
if (this.changeCb) {
|
|
this.changeCb(app, value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Application} app
|
|
* @param {Element} element
|
|
* @param {any} dialogs
|
|
*/
|
|
bind(app, element, dialogs) {
|
|
this.app = app;
|
|
this.element = element;
|
|
this.dialogs = dialogs;
|
|
}
|
|
|
|
getHtml() {
|
|
abstract;
|
|
return "";
|
|
}
|
|
|
|
syncValueToElement() {
|
|
abstract;
|
|
}
|
|
|
|
modify() {
|
|
abstract;
|
|
}
|
|
|
|
showRestartRequiredDialog() {
|
|
const { restart } = this.dialogs.showInfo(
|
|
T.dialogs.restartRequired.title,
|
|
T.dialogs.restartRequired.text,
|
|
this.app.platformWrapper.getSupportsRestart() ? ["later:grey", "restart:misc"] : ["ok:good"]
|
|
);
|
|
if (restart) {
|
|
restart.add(() => this.app.platformWrapper.performRestart());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {any} value
|
|
* @returns {boolean}
|
|
*/
|
|
validate(value) {
|
|
abstract;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export class EnumSetting extends BaseSetting {
|
|
constructor(
|
|
id,
|
|
{
|
|
options,
|
|
valueGetter,
|
|
textGetter,
|
|
descGetter = null,
|
|
category,
|
|
restartRequired = true,
|
|
iconPrefix = null,
|
|
changeCb = null,
|
|
magicValue = null,
|
|
enabled = true,
|
|
}
|
|
) {
|
|
super(id, category, changeCb, enabled);
|
|
|
|
this.options = options;
|
|
this.valueGetter = valueGetter;
|
|
this.textGetter = textGetter;
|
|
this.descGetter = descGetter || (() => null);
|
|
this.restartRequired = restartRequired;
|
|
this.iconPrefix = iconPrefix;
|
|
this.magicValue = magicValue;
|
|
}
|
|
|
|
getHtml() {
|
|
return `
|
|
<div class="setting cardbox ${this.enabled ? "enabled" : "disabled"}">
|
|
${this.enabled ? "" : standaloneOnlySettingHtml}
|
|
<div class="row">
|
|
<label>${T.settings.labels[this.id].title}</label>
|
|
<div class="value enum" data-setting="${this.id}"></div>
|
|
</div>
|
|
<div class="desc">
|
|
${T.settings.labels[this.id].description}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
validate(value) {
|
|
if (value === this.magicValue) {
|
|
return true;
|
|
}
|
|
|
|
const availableValues = this.options.map(option => this.valueGetter(option));
|
|
if (availableValues.indexOf(value) < 0) {
|
|
logger.error(
|
|
"Value '" + value + "' is not contained in available values:",
|
|
availableValues,
|
|
"of",
|
|
this.id
|
|
);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
syncValueToElement() {
|
|
const value = this.app.settings.getSetting(this.id);
|
|
let displayText = "???";
|
|
const matchedInstance = this.options.find(data => this.valueGetter(data) === value);
|
|
if (matchedInstance) {
|
|
displayText = this.textGetter(matchedInstance);
|
|
} else {
|
|
logger.warn("Setting value", value, "not found for", this.id, "!");
|
|
}
|
|
this.element.innerText = displayText;
|
|
}
|
|
|
|
modify() {
|
|
const { optionSelected } = this.dialogs.showOptionChooser(T.settings.labels[this.id].title, {
|
|
active: this.app.settings.getSetting(this.id),
|
|
options: this.options.map(option => ({
|
|
value: this.valueGetter(option),
|
|
text: this.textGetter(option),
|
|
desc: this.descGetter(option),
|
|
iconPrefix: this.iconPrefix,
|
|
})),
|
|
});
|
|
optionSelected.add(value => {
|
|
this.app.settings.updateSetting(this.id, value);
|
|
this.syncValueToElement();
|
|
|
|
if (this.restartRequired) {
|
|
this.showRestartRequiredDialog();
|
|
}
|
|
|
|
if (this.changeCb) {
|
|
this.changeCb(this.app, value);
|
|
}
|
|
}, this);
|
|
}
|
|
}
|
|
|
|
export class BoolSetting extends BaseSetting {
|
|
constructor(id, category, changeCb = null, enabled = true) {
|
|
super(id, category, changeCb, enabled);
|
|
}
|
|
|
|
getHtml() {
|
|
return `
|
|
<div class="setting cardbox ${this.enabled ? "enabled" : "disabled"}">
|
|
${this.enabled ? "" : standaloneOnlySettingHtml}
|
|
|
|
<div class="row">
|
|
<label>${T.settings.labels[this.id].title}</label>
|
|
<div class="value checkbox checked" data-setting="${this.id}">
|
|
<span class="knob"></span>
|
|
</div>
|
|
</div>
|
|
<div class="desc">
|
|
${T.settings.labels[this.id].description}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
syncValueToElement() {
|
|
const value = this.app.settings.getSetting(this.id);
|
|
this.element.classList.toggle("checked", value);
|
|
}
|
|
|
|
modify() {
|
|
const newValue = !this.app.settings.getSetting(this.id);
|
|
this.app.settings.updateSetting(this.id, newValue);
|
|
this.syncValueToElement();
|
|
|
|
if (this.changeCb) {
|
|
this.changeCb(this.app, newValue);
|
|
}
|
|
}
|
|
|
|
validate(value) {
|
|
return typeof value === "boolean";
|
|
}
|
|
}
|