|
|
@ -7,6 +7,8 @@ interface settingsBoolEvent extends Event {
|
|
|
|
interface Meta {
|
|
|
|
interface Meta {
|
|
|
|
name: string;
|
|
|
|
name: string;
|
|
|
|
description: string;
|
|
|
|
description: string;
|
|
|
|
|
|
|
|
depends_true?: string;
|
|
|
|
|
|
|
|
depends_false?: string;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interface Setting {
|
|
|
|
interface Setting {
|
|
|
@ -16,13 +18,21 @@ interface Setting {
|
|
|
|
requires_restart: boolean;
|
|
|
|
requires_restart: boolean;
|
|
|
|
type: string;
|
|
|
|
type: string;
|
|
|
|
value: string | boolean | number;
|
|
|
|
value: string | boolean | number;
|
|
|
|
depends_true?: Setting;
|
|
|
|
depends_true?: string;
|
|
|
|
depends_false?: Setting;
|
|
|
|
depends_false?: string;
|
|
|
|
|
|
|
|
|
|
|
|
asElement: () => HTMLElement;
|
|
|
|
asElement: () => HTMLElement;
|
|
|
|
update: (s: Setting) => void;
|
|
|
|
update: (s: Setting) => void;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const splitDependant = (section: string, dep: string): string[] => {
|
|
|
|
|
|
|
|
let parts = dep.split("|");
|
|
|
|
|
|
|
|
if (parts.length == 1) {
|
|
|
|
|
|
|
|
parts = [section, parts[0]];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return parts
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class DOMInput {
|
|
|
|
class DOMInput {
|
|
|
|
protected _input: HTMLInputElement;
|
|
|
|
protected _input: HTMLInputElement;
|
|
|
|
private _container: HTMLDivElement;
|
|
|
|
private _container: HTMLDivElement;
|
|
|
@ -76,7 +86,7 @@ class DOMInput {
|
|
|
|
<i class="icon ri-information-line"></i>
|
|
|
|
<i class="icon ri-information-line"></i>
|
|
|
|
<span class="content sm"></span>
|
|
|
|
<span class="content sm"></span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<input type="${inputType}" class="input ~neutral !normal mt-half">
|
|
|
|
<input type="${inputType}" class="input ~neutral !normal mt-half mb-half">
|
|
|
|
</label>
|
|
|
|
</label>
|
|
|
|
`;
|
|
|
|
`;
|
|
|
|
this._tooltip = this._container.querySelector("div.setting-tooltip") as HTMLDivElement;
|
|
|
|
this._tooltip = this._container.querySelector("div.setting-tooltip") as HTMLDivElement;
|
|
|
@ -84,11 +94,15 @@ class DOMInput {
|
|
|
|
this._restart = this._container.querySelector("span.setting-restart") as HTMLSpanElement;
|
|
|
|
this._restart = this._container.querySelector("span.setting-restart") as HTMLSpanElement;
|
|
|
|
this._input = this._container.querySelector("input[type=" + inputType + "]") as HTMLInputElement;
|
|
|
|
this._input = this._container.querySelector("input[type=" + inputType + "]") as HTMLInputElement;
|
|
|
|
if (setting.depends_false || setting.depends_true) {
|
|
|
|
if (setting.depends_false || setting.depends_true) {
|
|
|
|
let dependant = setting.depends_true || setting.depends_false;
|
|
|
|
let dependant = splitDependant(section, setting.depends_true || setting.depends_false);
|
|
|
|
let state = true;
|
|
|
|
let state = true;
|
|
|
|
if (setting.depends_false) { state = false; }
|
|
|
|
if (setting.depends_false) { state = false; }
|
|
|
|
document.addEventListener(`settings-${section}-${dependant}`, (event: settingsBoolEvent) => {
|
|
|
|
document.addEventListener(`settings-${dependant[0]}-${dependant[1]}`, (event: settingsBoolEvent) => {
|
|
|
|
this._input.disabled = (event.detail !== state);
|
|
|
|
if (Boolean(event.detail) !== state) {
|
|
|
|
|
|
|
|
this._input.parentElement.classList.add("unfocused");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this._input.parentElement.classList.remove("unfocused");
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const onValueChange = () => {
|
|
|
|
const onValueChange = () => {
|
|
|
@ -206,7 +220,7 @@ class DOMBool implements SBool {
|
|
|
|
this._container = document.createElement("div");
|
|
|
|
this._container = document.createElement("div");
|
|
|
|
this._container.classList.add("setting");
|
|
|
|
this._container.classList.add("setting");
|
|
|
|
this._container.innerHTML = `
|
|
|
|
this._container.innerHTML = `
|
|
|
|
<label class="switch">
|
|
|
|
<label class="switch mb-half">
|
|
|
|
<input type="checkbox">
|
|
|
|
<input type="checkbox">
|
|
|
|
<span class="setting-label"></span> <span class="setting-required"></span> <span class="setting-restart"></span>
|
|
|
|
<span class="setting-label"></span> <span class="setting-required"></span> <span class="setting-restart"></span>
|
|
|
|
<div class="setting-tooltip tooltip right unfocused">
|
|
|
|
<div class="setting-tooltip tooltip right unfocused">
|
|
|
@ -230,11 +244,15 @@ class DOMBool implements SBool {
|
|
|
|
document.addEventListener(`settings-loaded`, onValueChange);
|
|
|
|
document.addEventListener(`settings-loaded`, onValueChange);
|
|
|
|
|
|
|
|
|
|
|
|
if (setting.depends_false || setting.depends_true) {
|
|
|
|
if (setting.depends_false || setting.depends_true) {
|
|
|
|
let dependant = setting.depends_true || setting.depends_false;
|
|
|
|
let dependant = splitDependant(section, setting.depends_true || setting.depends_false);
|
|
|
|
let state = true;
|
|
|
|
let state = true;
|
|
|
|
if (setting.depends_false) { state = false; }
|
|
|
|
if (setting.depends_false) { state = false; }
|
|
|
|
document.addEventListener(`settings-${section}-${dependant}`, (event: settingsBoolEvent) => {
|
|
|
|
document.addEventListener(`settings-${dependant[0]}-${dependant[1]}`, (event: settingsBoolEvent) => {
|
|
|
|
this._input.disabled = (event.detail !== state);
|
|
|
|
if (Boolean(event.detail) !== state) {
|
|
|
|
|
|
|
|
this._input.parentElement.classList.add("unfocused");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this._input.parentElement.classList.remove("unfocused");
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.update(setting);
|
|
|
|
this.update(setting);
|
|
|
@ -251,7 +269,7 @@ class DOMBool implements SBool {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interface SSelect extends Setting {
|
|
|
|
interface SSelect extends Setting {
|
|
|
|
options: string[];
|
|
|
|
options: string[][];
|
|
|
|
value: string;
|
|
|
|
value: string;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
class DOMSelect implements SSelect {
|
|
|
|
class DOMSelect implements SSelect {
|
|
|
@ -260,7 +278,7 @@ class DOMSelect implements SSelect {
|
|
|
|
private _tooltip: HTMLDivElement;
|
|
|
|
private _tooltip: HTMLDivElement;
|
|
|
|
private _required: HTMLSpanElement;
|
|
|
|
private _required: HTMLSpanElement;
|
|
|
|
private _restart: HTMLSpanElement;
|
|
|
|
private _restart: HTMLSpanElement;
|
|
|
|
private _options: string[];
|
|
|
|
private _options: string[][];
|
|
|
|
type: string = "bool";
|
|
|
|
type: string = "bool";
|
|
|
|
|
|
|
|
|
|
|
|
get name(): string { return this._container.querySelector("span.setting-label").textContent; }
|
|
|
|
get name(): string { return this._container.querySelector("span.setting-label").textContent; }
|
|
|
@ -301,12 +319,12 @@ class DOMSelect implements SSelect {
|
|
|
|
get value(): string { return this._select.value; }
|
|
|
|
get value(): string { return this._select.value; }
|
|
|
|
set value(v: string) { this._select.value = v; }
|
|
|
|
set value(v: string) { this._select.value = v; }
|
|
|
|
|
|
|
|
|
|
|
|
get options(): string[] { return this._options; }
|
|
|
|
get options(): string[][] { return this._options; }
|
|
|
|
set options(opt: string[]) {
|
|
|
|
set options(opt: string[][]) {
|
|
|
|
this._options = opt;
|
|
|
|
this._options = opt;
|
|
|
|
let innerHTML = "";
|
|
|
|
let innerHTML = "";
|
|
|
|
for (let option of this._options) {
|
|
|
|
for (let option of this._options) {
|
|
|
|
innerHTML += `<option value="${option}">${option}</option>`;
|
|
|
|
innerHTML += `<option value="${option[0]}">${option[1]}</option>`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this._select.innerHTML = innerHTML;
|
|
|
|
this._select.innerHTML = innerHTML;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -322,7 +340,7 @@ class DOMSelect implements SSelect {
|
|
|
|
<i class="icon ri-information-line"></i>
|
|
|
|
<i class="icon ri-information-line"></i>
|
|
|
|
<span class="content sm"></span>
|
|
|
|
<span class="content sm"></span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="select ~neutral !normal mt-half">
|
|
|
|
<div class="select ~neutral !normal mt-half mb-half">
|
|
|
|
<select class="settings-select"></select>
|
|
|
|
<select class="settings-select"></select>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</label>
|
|
|
|
</label>
|
|
|
@ -332,11 +350,15 @@ class DOMSelect implements SSelect {
|
|
|
|
this._restart = this._container.querySelector("span.setting-restart") as HTMLSpanElement;
|
|
|
|
this._restart = this._container.querySelector("span.setting-restart") as HTMLSpanElement;
|
|
|
|
this._select = this._container.querySelector("select.settings-select") as HTMLSelectElement;
|
|
|
|
this._select = this._container.querySelector("select.settings-select") as HTMLSelectElement;
|
|
|
|
if (setting.depends_false || setting.depends_true) {
|
|
|
|
if (setting.depends_false || setting.depends_true) {
|
|
|
|
let dependant = setting.depends_true || setting.depends_false;
|
|
|
|
let dependant = splitDependant(section, setting.depends_true || setting.depends_false);
|
|
|
|
let state = true;
|
|
|
|
let state = true;
|
|
|
|
if (setting.depends_false) { state = false; }
|
|
|
|
if (setting.depends_false) { state = false; }
|
|
|
|
document.addEventListener(`settings-${section}-${dependant}`, (event: settingsBoolEvent) => {
|
|
|
|
document.addEventListener(`settings-${dependant[0]}-${dependant[1]}`, (event: settingsBoolEvent) => {
|
|
|
|
this._input.disabled = (event.detail !== state);
|
|
|
|
if (Boolean(event.detail) !== state) {
|
|
|
|
|
|
|
|
this._container.classList.add("unfocused");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this._container.classList.remove("unfocused");
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const onValueChange = () => {
|
|
|
|
const onValueChange = () => {
|
|
|
@ -345,6 +367,7 @@ class DOMSelect implements SSelect {
|
|
|
|
if (this.requires_restart) { document.dispatchEvent(new CustomEvent("settings-requires-restart")); }
|
|
|
|
if (this.requires_restart) { document.dispatchEvent(new CustomEvent("settings-requires-restart")); }
|
|
|
|
};
|
|
|
|
};
|
|
|
|
this._select.onchange = onValueChange;
|
|
|
|
this._select.onchange = onValueChange;
|
|
|
|
|
|
|
|
document.addEventListener(`settings-loaded`, onValueChange);
|
|
|
|
|
|
|
|
|
|
|
|
const message = document.getElementById("settings-message") as HTMLElement;
|
|
|
|
const message = document.getElementById("settings-message") as HTMLElement;
|
|
|
|
message.innerHTML = window.lang.var("strings",
|
|
|
|
message.innerHTML = window.lang.var("strings",
|
|
|
@ -353,9 +376,6 @@ class DOMSelect implements SSelect {
|
|
|
|
`<span class="badge ~info">R</span>`
|
|
|
|
`<span class="badge ~info">R</span>`
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.update(setting);
|
|
|
|
this.update(setting);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
update = (s: SSelect) => {
|
|
|
|
update = (s: SSelect) => {
|
|
|
@ -391,6 +411,7 @@ class sectionPanel {
|
|
|
|
<span class="heading">${s.meta.name}</span>
|
|
|
|
<span class="heading">${s.meta.name}</span>
|
|
|
|
<p class="support lg">${s.meta.description}</p>
|
|
|
|
<p class="support lg">${s.meta.description}</p>
|
|
|
|
`;
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
this.update(s);
|
|
|
|
this.update(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
update = (s: Section) => {
|
|
|
|
update = (s: Section) => {
|
|
|
@ -443,8 +464,6 @@ class sectionPanel {
|
|
|
|
asElement = (): HTMLDivElement => { return this._section; }
|
|
|
|
asElement = (): HTMLDivElement => { return this._section; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interface Settings {
|
|
|
|
interface Settings {
|
|
|
|
order: string[];
|
|
|
|
order: string[];
|
|
|
|
sections: { [sectionName: string]: Section };
|
|
|
|
sections: { [sectionName: string]: Section };
|
|
|
@ -469,6 +488,18 @@ export class settingsList {
|
|
|
|
button.classList.add("button", "~neutral", "!low", "settings-section-button", "mb-half");
|
|
|
|
button.classList.add("button", "~neutral", "!low", "settings-section-button", "mb-half");
|
|
|
|
button.textContent = s.meta.name;
|
|
|
|
button.textContent = s.meta.name;
|
|
|
|
button.onclick = () => { this._showPanel(name); };
|
|
|
|
button.onclick = () => { this._showPanel(name); };
|
|
|
|
|
|
|
|
if (s.meta.depends_true || s.meta.depends_false) {
|
|
|
|
|
|
|
|
let dependant = splitDependant(name, s.meta.depends_true || s.meta.depends_false);
|
|
|
|
|
|
|
|
let state = true;
|
|
|
|
|
|
|
|
if (s.meta.depends_false) { state = false; }
|
|
|
|
|
|
|
|
document.addEventListener(`settings-${dependant[0]}-${dependant[1]}`, (event: settingsBoolEvent) => {
|
|
|
|
|
|
|
|
if (Boolean(event.detail) !== state) {
|
|
|
|
|
|
|
|
button.classList.add("unfocused");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
button.classList.remove("unfocused");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
this._buttons[name] = button;
|
|
|
|
this._buttons[name] = button;
|
|
|
|
this._sidebar.appendChild(this._buttons[name]);
|
|
|
|
this._sidebar.appendChild(this._buttons[name]);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -549,9 +580,9 @@ export class settingsList {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this._showPanel(settings.order[0]);
|
|
|
|
this._showPanel(settings.order[0]);
|
|
|
|
this._needsRestart = false;
|
|
|
|
|
|
|
|
document.dispatchEvent(new CustomEvent("settings-loaded"));
|
|
|
|
document.dispatchEvent(new CustomEvent("settings-loaded"));
|
|
|
|
this._saveButton.classList.add("unfocused");
|
|
|
|
this._saveButton.classList.add("unfocused");
|
|
|
|
|
|
|
|
this._needsRestart = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|