feat(setting-tab): general settings now working

This commit is contained in:
EloiMusk 2023-03-09 11:19:51 +01:00
parent 0c68306169
commit 10f3f10080
No known key found for this signature in database
GPG key ID: A59863E13934DD4F
3 changed files with 225 additions and 22 deletions

View file

@ -109,15 +109,6 @@ export default class PrioPlugin extends Plugin {
// This adds a settings tab so the user can configure various aspects of the plugin
this.addSettingTab(new SettingTab(this.app, this));
// If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin)
// Using this function will automatically remove the event listener when this plugin is disabled.
// this.registerDomEvent(document, 'click', (evt: MouseEvent) => {
// console.log('click', evt);
// });
// When registering intervals, this function will automatically clear the interval when the plugin is disabled.
this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000));
}
onunload() {

View file

@ -1,11 +1,4 @@
/*
This CSS file will be included with your plugin, and
available in the app when your plugin is enabled.
If your plugin does not need CSS, delete this file.
*/
/*Preset list setting*/
.preset-list {
display: flex;
flex-wrap: nowrap;
@ -30,10 +23,27 @@ If your plugin does not need CSS, delete this file.
background-color: var(--background-modifier-hover);
}
.mod-danger {
background-color: var(--background-modifier-error);
color: var(--text-error);
}
.mod-danger:hover {
background-color: var(--background-modifier-error-hover);
color: var(--text-faint);
}
.btn {
margin: 5px;
}
.btn:disabled {
background-color: var(--color-base-10) !important;
color: var(--color-base-60) !important;
border: none !important;
box-shadow: none !important;
}
.btn-primary {
background-color: var(--interactive-accent);
}
@ -42,7 +52,38 @@ If your plugin does not need CSS, delete this file.
background-color: var(--interactive-accent-hover);
}
/*---------------------*/
/*Level Slider setting*/
.level-text {
max-width: 50px;
margin: 5px;
}
/*---------------------*/
/*Level aliases list setting*/
.level-aliases-list {
display: flex;
flex-flow: column nowrap;
width: 100%;
padding: 10px;
}
.level-aliases-list-item {
align-items: center;
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
padding: 5px;
border-top: 1px solid var(--background-modifier-border);
border-bottom: 1px solid var(--background-modifier-border);
}
.level-aliases-list-item-input {
margin-left: 5px;
max-width: 80%;
}
/*---------------------*/

View file

@ -1,22 +1,43 @@
import {App, PluginSettingTab, Setting, SliderComponent} from "obsidian";
import {App, Modal, Notice, PluginSettingTab, Setting, SliderComponent} from "obsidian";
import PrioPlugin from "../main";
import {Preset} from "./Presets";
import {PrioPluginSettings} from "./Settings";
export class SettingTab extends PluginSettingTab {
plugin: PrioPlugin;
saveConfirm: SaveConfirm;
previousSettings: PrioPluginSettings;
modified = false;
constructor(app: App, plugin: PrioPlugin) {
super(app, plugin);
this.plugin = plugin;
this.saveConfirm = new SaveConfirm(this);
}
hide(): any {
if (this.modified) {
this.saveConfirm.open();
return;
}
return super.hide();
}
display(): void {
this.previousSettings = Object.assign({}, this.plugin.settings);
const {containerEl} = this;
this.plugin.registerDomEvent(document, 'change', () => {
this.modified = true;
});
containerEl.empty();
let presets: Preset[] = this.plugin.settings.presets ?? [];
const saveButton = createEl('button', {text: 'Save', cls: ['mod-cta', 'mod-primary', 'btn']});
containerEl.createEl('h2', {text: 'General Settings'});
@ -68,6 +89,8 @@ export class SettingTab extends PluginSettingTab {
value = 10;
}
levelSlider.setValue(value);
this.plugin.settings.levels = value;
this.generateLevelAliasList(this.plugin.settings, levelAliasesList, [saveButton]);
});
this.generatePresetList(presets, presetList);
@ -83,10 +106,70 @@ export class SettingTab extends PluginSettingTab {
.onChange(async (value) => {
this.plugin.settings.levels = value;
levelText.value = value.toString();
this.generateLevelAliasList(this.plugin.settings, levelAliasesList, [saveButton]);
})
.setDynamicTooltip()
})
});
new Setting(containerEl).setName('Level Aliases').setDesc('Set the aliases for each level.');
const levelAliasesContainer = containerEl.createEl('div');
const levelAliasesList = createEl('ol', {
cls: 'level-aliases-list',
parent: levelAliasesContainer
});
this.generateLevelAliasList(this.plugin.settings, levelAliasesList, [saveButton]);
containerEl.append(saveButton);
saveButton.addEventListener('click', () => {
if (!this.isValid(levelAliasesList, [saveButton])) {
return;
}
this.setAliases(this.plugin.settings, levelAliasesList);
this.plugin.saveSettings().then(() => {
this.plugin.loadSettings().then(() => {
new Notice('Settings saved successfully!');
});
});
});
}
setAliases = (settings: PrioPluginSettings, levelAliasesList: HTMLOListElement) => {
const inputs = levelAliasesList.querySelectorAll('input');
const aliases: string[] = [];
inputs.forEach(input => {
aliases.push((input as HTMLInputElement).value);
});
aliases.map((alias, index) => {
this.plugin.settings.levelAliases[index] = alias;
});
}
generateLevelAliasList = (settings: PrioPluginSettings, levelAliasesList: HTMLOListElement, buttons: HTMLButtonElement[]) => {
levelAliasesList.empty();
const els: HTMLElement[] = [];
while (settings.levels > levelAliasesList.children.length) {
const el = createEl('li', {
text: `${levelAliasesList.children.length + 1}`,
cls: 'level-aliases-list-item',
parent: levelAliasesList
});
const input = el.createEl('input', {
cls: 'level-aliases-list-item-input',
value: settings.levelAliases[levelAliasesList.children.length - 1] ?? '',
})
input.addEventListener('blur', (event) => {
const valid = this.validateLevelAlias((event.target as HTMLInputElement).value, parseInt((event.target as HTMLInputElement).parentElement?.textContent ?? '') - 1, settings.levelAliases.slice(0, settings.levels));
for (const button of buttons) {
button.disabled = !valid;
}
});
els.push(el);
}
return els;
}
generatePresetList = (presets: Preset[], presetList: HTMLOListElement) => (presets || []).map(preset => {
@ -100,14 +183,14 @@ export class SettingTab extends PluginSettingTab {
});
btnGroup.createEl('button', {
text: 'Select',
cls: ['preset-list-item-select', 'btn', 'btn-primary'],
text: 'Apply',
cls: ['preset-list-item-apply', 'btn', 'btn-primary'],
attr: {
'onclick': 'alert("Preset Selected")'
}
})
btnGroup.createEl('button', {
text: 'Save',
text: 'Overwrite',
cls: ['preset-list-item-save', 'btn', 'btn-primary'],
attr: {
'onclick': 'alert("Save Preset")'
@ -115,4 +198,92 @@ export class SettingTab extends PluginSettingTab {
})
return el;
});
isValid = (levelAliasesList: HTMLOListElement, buttons: HTMLButtonElement[]) => {
const inputs = levelAliasesList.querySelectorAll('input');
const aliases: string[] = [];
inputs.forEach(input => {
aliases.push((input as HTMLInputElement).value);
});
if (aliases.length !== new Set(aliases).size) {
new Notice('Level aliases must be unique.');
return false;
}
if (aliases.some(alias => alias.length === 0)) {
new Notice('Level aliases must not be empty.');
return false;
}
return true;
}
validateLevelAlias = (alias: string, index: number, aliases: string[]) => {
if (aliases.indexOf(alias) != index && aliases.includes(alias)) {
new Notice('Alias already exists!');
return false;
}
if (alias.length < 1) {
new Notice('Alias must be at least 1 character long!');
return false;
}
if (alias.match(/[^a-zA-Z0-9]/)) {
new Notice('Alias must only contain alphanumeric characters!');
return false;
}
return true;
}
}
class SaveConfirm extends Modal {
private settingsTab: SettingTab;
constructor(settingsTab: SettingTab) {
super(settingsTab.app);
this.settingsTab = settingsTab;
}
open() {
super.open();
}
onOpen() {
const {contentEl} = this;
contentEl.setText('You have unsaved changes. Would you like to save them?');
const btnGroup = contentEl.createEl('div', {
cls: 'save-btn-group'
});
const saveButton = createEl('button', {
text: 'Save',
cls: ['btn', 'mod-cta'],
});
const discardButton = createEl('button', {
text: 'Discard',
cls: ['btn', 'mod-danger'],
});
saveButton.addEventListener('click', () => {
this.settingsTab.plugin.saveSettings().then(() => {
this.settingsTab.plugin.loadSettings().then(() => {
new Notice('Settings saved successfully!');
});
});
this.close();
});
discardButton.addEventListener('click', () => {
this.settingsTab.plugin.loadSettings().then(() => {
new Notice('Settings discarded successfully!');
});
this.close();
});
btnGroup.append(saveButton);
btnGroup.append(discardButton);
}
onClose() {
const {contentEl} = this;
contentEl.empty();
}
}