mirror of
https://github.com/Kornstalx/5etools-mirror-2.github.io.git
synced 2025-10-28 20:45:35 -05:00
v1.208.0
This commit is contained in:
10
js/utils-config/util-config-helpers.js
Normal file
10
js/utils-config/util-config-helpers.js
Normal file
@@ -0,0 +1,10 @@
|
||||
export class UtilConfigHelpers {
|
||||
static packSettingId (groupId, configId) {
|
||||
return `${groupId}.${configId}`;
|
||||
}
|
||||
|
||||
static unpackSettingId (settingId) {
|
||||
const [groupId, configId] = settingId.split(".");
|
||||
return {groupId, configId};
|
||||
}
|
||||
}
|
||||
38
js/utils-config/util-config-settings-group.js
Normal file
38
js/utils-config/util-config-settings-group.js
Normal file
@@ -0,0 +1,38 @@
|
||||
export class ConfigSettingsGroup {
|
||||
constructor (
|
||||
{
|
||||
groupId,
|
||||
name,
|
||||
configSettings,
|
||||
},
|
||||
) {
|
||||
this._groupId = groupId;
|
||||
this._name = name;
|
||||
this._configSettings = configSettings;
|
||||
|
||||
this._configSettings
|
||||
.forEach(configSetting => configSetting.setGroupId(this._groupId));
|
||||
}
|
||||
|
||||
get groupId () { return this._groupId; }
|
||||
|
||||
render (rdState, {isLast = false} = {}) {
|
||||
const wrpRows = ee`<div></div>`;
|
||||
|
||||
ee`<div class="w-100">
|
||||
<h4>${this._name}</h4>
|
||||
${wrpRows}
|
||||
${isLast ? null : `<hr class="hr-3 mb-1">`}
|
||||
</div>`
|
||||
.appendTo(rdState.wrp);
|
||||
|
||||
this._configSettings
|
||||
.forEach(configSetting => configSetting.render(rdState, wrpRows));
|
||||
}
|
||||
|
||||
mutDefaults (config) {
|
||||
const group = config[this._groupId] ||= {};
|
||||
this._configSettings
|
||||
.forEach(configSetting => configSetting.mutDefaults(group));
|
||||
}
|
||||
}
|
||||
66
js/utils-config/utils-config-config.js
Normal file
66
js/utils-config/utils-config-config.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import {SETTINGS_GROUPS} from "./utils-config-registry.js";
|
||||
import {UtilConfigHelpers} from "./util-config-helpers.js";
|
||||
|
||||
export class VetoolsConfig {
|
||||
static _STORAGE_KEY = "config";
|
||||
|
||||
static _CONFIG = null;
|
||||
|
||||
static _init () {
|
||||
if (this._CONFIG) return;
|
||||
|
||||
this._CONFIG = StorageUtil.syncGet(this._STORAGE_KEY) || {};
|
||||
|
||||
SETTINGS_GROUPS
|
||||
.forEach(settingsGroup => settingsGroup.mutDefaults(this._CONFIG));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static get (groupId, configId) {
|
||||
this._init();
|
||||
return MiscUtil.get(this._CONFIG, groupId, configId);
|
||||
}
|
||||
|
||||
static set (groupId, configId, val) {
|
||||
this._init();
|
||||
MiscUtil.set(this._CONFIG, groupId, configId, val);
|
||||
this._save();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static _save () {
|
||||
StorageUtil.syncSet(this._STORAGE_KEY, this._CONFIG);
|
||||
}
|
||||
|
||||
static _saveThrottled = MiscUtil.throttle(this._save.bind(this), 50);
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static getConfigComp () {
|
||||
this._init();
|
||||
|
||||
const state = {};
|
||||
Object.entries(this._CONFIG)
|
||||
.forEach(([groupId, groupTo]) => {
|
||||
Object.entries(groupTo)
|
||||
.forEach(([configId, val]) => {
|
||||
state[UtilConfigHelpers.packSettingId(groupId, configId)] = MiscUtil.copyFast(val);
|
||||
});
|
||||
});
|
||||
|
||||
const comp = BaseComponent.fromObject(state, "*");
|
||||
comp._addHookAllBase(() => {
|
||||
Object.entries(comp._state)
|
||||
.forEach(([settingId, v]) => {
|
||||
const {groupId, configId} = UtilConfigHelpers.unpackSettingId(settingId);
|
||||
MiscUtil.set(this._CONFIG, groupId, configId, v);
|
||||
});
|
||||
|
||||
this._saveThrottled();
|
||||
});
|
||||
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
74
js/utils-config/utils-config-registry.js
Normal file
74
js/utils-config/utils-config-registry.js
Normal file
@@ -0,0 +1,74 @@
|
||||
import {ConfigSettingsGroup} from "./util-config-settings-group.js";
|
||||
import {ConfigSettingBoolean, ConfigSettingEnum, ConfigSettingExternal} from "./utils-config-setting-base.js";
|
||||
|
||||
const settingsGroupStyleSwitcher = new ConfigSettingsGroup({
|
||||
groupId: "styleSwitcher",
|
||||
name: "Appearance",
|
||||
configSettings: [
|
||||
new (
|
||||
class extends ConfigSettingExternal {
|
||||
_configId = "theme";
|
||||
_name = "Theme";
|
||||
_help = "The color theme to be applied.";
|
||||
_isRowLabel = true;
|
||||
|
||||
_getEleExternal () { return StyleSwitcher.getSelStyle(); }
|
||||
}
|
||||
)(),
|
||||
new (
|
||||
class extends ConfigSettingExternal {
|
||||
_configId = "isWideMode";
|
||||
_name = "Wide Mode (Experimental)";
|
||||
_help = "This feature is unsupported. Expect bugs.";
|
||||
_isRowLabel = true;
|
||||
|
||||
_getEleExternal () { return StyleSwitcher.getCbWide(); }
|
||||
}
|
||||
)(),
|
||||
],
|
||||
});
|
||||
|
||||
const _MARKDOWN_TAG_RENDER_MODES = {
|
||||
"convertMarkdown": "Convert to Markdown",
|
||||
"ignore": "Leave As-Is",
|
||||
"convertText": "Convert to Text",
|
||||
};
|
||||
|
||||
const settingsGroupMarkdown = new ConfigSettingsGroup({
|
||||
groupId: "markdown",
|
||||
name: "Markdown",
|
||||
configSettings: [
|
||||
new ConfigSettingEnum({
|
||||
configId: "tagRenderMode",
|
||||
name: `Tag Handling (<code>@tag</code>)`,
|
||||
help: `THe output to produce when rendering a 5etools "@tag".`,
|
||||
isRowLabel: true,
|
||||
default: "convertMarkdown",
|
||||
values: [
|
||||
"convertMarkdown",
|
||||
"ignore",
|
||||
"convertText",
|
||||
],
|
||||
fnDisplay: it => _MARKDOWN_TAG_RENDER_MODES[it] || it,
|
||||
}),
|
||||
new ConfigSettingBoolean({
|
||||
configId: "isAddColumnBreaks",
|
||||
name: `Add GM Binder Column Breaks (<code>\\\\columnbreak</code>)`,
|
||||
help: `If "\\\\columnbreak"s should be added to exported Markdown, at an approximate column breakpoint.`,
|
||||
isRowLabel: true,
|
||||
default: false,
|
||||
}),
|
||||
new ConfigSettingBoolean({
|
||||
configId: "isAddPageBreaks",
|
||||
name: `Add GM Binder Page Breaks (<code>\\\\pagebreak</code>)`,
|
||||
help: `If "\\\\pagebreak"s should be added to exported Markdown, at an approximate page breakpoint.`,
|
||||
isRowLabel: true,
|
||||
default: false,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export const SETTINGS_GROUPS = [
|
||||
settingsGroupStyleSwitcher,
|
||||
settingsGroupMarkdown,
|
||||
];
|
||||
118
js/utils-config/utils-config-setting-base.js
Normal file
118
js/utils-config/utils-config-setting-base.js
Normal file
@@ -0,0 +1,118 @@
|
||||
import {UtilConfigHelpers} from "./util-config-helpers.js";
|
||||
|
||||
// TODO rename this file
|
||||
|
||||
/** @abstract */
|
||||
class _ConfigSettingBase {
|
||||
_groupId;
|
||||
_configId;
|
||||
_name;
|
||||
_help;
|
||||
|
||||
_isRowLabel = false;
|
||||
|
||||
constructor (
|
||||
{
|
||||
configId,
|
||||
name,
|
||||
help,
|
||||
|
||||
isRowLabel,
|
||||
} = {},
|
||||
) {
|
||||
this._configId = configId;
|
||||
this._name = name;
|
||||
this._help = help;
|
||||
this._isRowLabel = isRowLabel;
|
||||
}
|
||||
|
||||
setGroupId (groupId) { this._groupId = groupId; }
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
render (rdState, wrpRows) {
|
||||
const tag = this._isRowLabel ? "label" : "div";
|
||||
|
||||
ee`<${tag} class="py-1 w-100 split-v-center" title="${this._help.qq()}">
|
||||
${this._renderLabel(rdState)}
|
||||
${this._renderUi(rdState)}
|
||||
</${tag}>`
|
||||
.appendTo(wrpRows);
|
||||
}
|
||||
|
||||
_renderLabel (rdState) {
|
||||
return `<div class="w-66 no-shrink mr-2">${this._name}</div>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {HTMLElementModified}
|
||||
*/
|
||||
_renderUi (rdState) { throw new Error("Unimplemented!"); }
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @abstract */
|
||||
mutDefaults (group) {
|
||||
throw new Error("Unimplemented!");
|
||||
}
|
||||
}
|
||||
|
||||
/** @abstract */
|
||||
export class ConfigSettingExternal extends _ConfigSettingBase {
|
||||
_renderUi (rdState) { return this._getEleExternal(); }
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {HTMLElementModified}
|
||||
*/
|
||||
_getEleExternal () { throw new Error("Unimplemented!"); }
|
||||
|
||||
mutDefaults (group) { /* No-op */ }
|
||||
}
|
||||
|
||||
/** @abstract */
|
||||
class _ConfigSettingStandardBase extends _ConfigSettingBase {
|
||||
_default;
|
||||
|
||||
constructor (opts) {
|
||||
super(opts);
|
||||
this._default = opts.default;
|
||||
}
|
||||
|
||||
mutDefaults (group) {
|
||||
if (group[this._configId] !== undefined) return;
|
||||
group[this._configId] = this._default;
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigSettingBoolean extends _ConfigSettingStandardBase {
|
||||
_renderUi (rdState) {
|
||||
const prop = UtilConfigHelpers.packSettingId(this._groupId, this._configId);
|
||||
return ComponentUiUtil.getCbBool(rdState.comp, prop);
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigSettingEnum extends _ConfigSettingStandardBase {
|
||||
_values;
|
||||
_fnDisplay;
|
||||
|
||||
constructor ({values, fnDisplay, ...rest}) {
|
||||
super(rest);
|
||||
this._values = values;
|
||||
this._fnDisplay = fnDisplay;
|
||||
}
|
||||
|
||||
_renderUi (rdState) {
|
||||
const prop = UtilConfigHelpers.packSettingId(this._groupId, this._configId);
|
||||
|
||||
return ComponentUiUtil.getSelEnum(
|
||||
rdState.comp,
|
||||
prop,
|
||||
{
|
||||
values: this._values,
|
||||
fnDisplay: this._fnDisplay,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
79
js/utils-config/utils-config-ui.js
Normal file
79
js/utils-config/utils-config-ui.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import {VetoolsConfig} from "./utils-config-config.js";
|
||||
import {SETTINGS_GROUPS} from "./utils-config-registry.js";
|
||||
|
||||
class _ConfigRenderState {
|
||||
wrp;
|
||||
comp;
|
||||
|
||||
constructor (
|
||||
{
|
||||
wrp,
|
||||
comp,
|
||||
},
|
||||
) {
|
||||
this.wrp = wrp;
|
||||
this.comp = comp;
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigUi {
|
||||
constructor (
|
||||
{
|
||||
settingsGroups,
|
||||
},
|
||||
) {
|
||||
this._settingsGroups = settingsGroups;
|
||||
}
|
||||
|
||||
render (wrp) {
|
||||
const rdState = new _ConfigRenderState({
|
||||
wrp,
|
||||
comp: VetoolsConfig.getConfigComp(),
|
||||
});
|
||||
|
||||
this._settingsGroups
|
||||
.forEach((configSection, i, arr) => {
|
||||
configSection.render(rdState, {isLast: i === arr.length - 1});
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @param {?string[]} settingsGroupIds Subset of group IDs to display
|
||||
*/
|
||||
static show (
|
||||
{
|
||||
settingsGroupIds = null,
|
||||
} = {},
|
||||
) {
|
||||
const settingsGroups = settingsGroupIds
|
||||
? SETTINGS_GROUPS
|
||||
.filter(group => settingsGroupIds.includes(group.groupId))
|
||||
: SETTINGS_GROUPS;
|
||||
|
||||
const ui = new this({
|
||||
settingsGroups,
|
||||
});
|
||||
|
||||
const {$modalInner, $modalFooter, doClose} = UiUtil.getShowModal({
|
||||
isUncappedWidth: true,
|
||||
isUncappedHeight: true,
|
||||
title: "Preferences",
|
||||
headerType: 3,
|
||||
isHeaderBorder: true,
|
||||
overlayColor: "transparent",
|
||||
hasFooter: true,
|
||||
});
|
||||
|
||||
ui.render($modalInner[0]);
|
||||
|
||||
const btnClose = ee`<button class="btn btn-default btn-sm ml-auto">Close</button>`
|
||||
.onn("click", () => doClose());
|
||||
|
||||
ee`<div class="py-1 w-100 ve-flex-v-center">
|
||||
${btnClose}
|
||||
</div>`
|
||||
.appendTo($modalFooter[0]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user