oft/module/apps/OFTSettingsMenu.mjs

186 lines
5.1 KiB
JavaScript

import { __ID__, filePath } from "../consts.mjs";
const { HandlebarsApplicationMixin: HAM, ApplicationV2 } = foundry.applications.api;
export class OFTSettingsMenu extends HAM(ApplicationV2) {
// #region Options
static DEFAULT_OPTIONS = {
tag: `form`,
classes: [ __ID__ ],
window: {
icon: `fa-solid fa-gears`,
resizable: true,
contentClasses: [
`standard-form`,
],
controls: [
{
icon: `fa-solid fa-arrow-rotate-left`,
label: `PACKAGECONFIG.Reset`,
visible: true,
action: `resetDefaults`,
},
],
},
form: {
handler: this.#handleSubmit,
closeOnSubmit: true,
submitOnChange: false,
},
position: {
width: 544,
},
actions: {
resetDefaults: this.#resetDefaults,
},
};
static PARTS = {
settingsList: {
template: filePath(`templates/OFTSettingsMenu/settingsList.hbs`),
scrollable: [``],
},
footer: {
template: filePath(`templates/OFTSettingsMenu/footer.hbs`),
},
};
static _SETTINGS = [];
// #endregion Options
// #region Data Prep
async _prepareContext() {
return {
meta: {
idp: this.id,
},
};
};
#partContextPrep = {
settingsList: this._prepareSettingsListContext,
};
async _preparePartContext(partID, ctx) {
ctx = foundry.utils.deepClone(ctx);
const prepper = this.#partContextPrep[partID];
if (prepper && typeof prepper === `function`) {
await prepper.call(this, ctx);
};
return ctx;
};
async _prepareSettingsListContext(ctx) {
const canConfigure = game.user.can(`SETTINGS_MODIFY`);
ctx.settings = [];
const settingIDs = this.constructor._SETTINGS;
for ( const settingID of settingIDs ) {
const setting = game.settings.settings.get(settingID);
if ( !canConfigure && setting.scope === CONST.SETTING_SCOPES.WORLD ) { continue }
const data = {
label: setting.value,
value: game.settings.get(setting.namespace, setting.key),
menu: false,
};
// Define a DataField for each setting not originally defined with one
const fields = foundry.data.fields;
if ( setting.type instanceof fields.DataField ) {
data.field = setting.type;
}
else if ( setting.type === Boolean ) {
data.field = new fields.BooleanField({initial: setting.default ?? false});
}
else if ( setting.type === Number ) {
const {min, max, step} = setting.range ?? {};
data.field = new fields.NumberField({
required: true,
choices: setting.choices,
initial: setting.default,
min,
max,
step,
});
}
else if ( setting.filePicker ) {
const categories = {
audio: [`AUDIO`],
folder: [],
font: [`FONT`],
graphics: [`GRAPHICS`],
image: [`IMAGE`],
imagevideo: [`IMAGE`, `VIDEO`],
text: [`TEXT`],
video: [`VIDEO`],
}[setting.filePicker] ?? Object.keys(CONST.FILE_CATEGORIES).filter(c => c !== `HTML`);
if ( categories.length ) {
data.field = new fields.FilePathField({required: true, blank: true, categories});
}
else {
data.field = new fields.StringField({required: true}); // Folder paths cannot be FilePathFields
data.folderPicker = true;
}
}
else {
data.field = new fields.StringField({required: true, choices: setting.choices});
}
data.field.name = `${setting.namespace}.${setting.key}`;
data.field.label ||= game.i18n.localize(setting.name ?? ``);
data.field.hint ||= game.i18n.localize(setting.hint ?? ``);
// Categorize setting
ctx.settings.push(data);
};
};
// #endregion Data Prep
// #region Actions
/** @this {OFTSettingsMenu} */
static async #handleSubmit(_event, _form, formData) {
let requiresClientReload = false;
let requiresWorldReload = false;
for ( const [key, value] of Object.entries(formData.object) ) {
const setting = game.settings.settings.get(key);
if ( !setting ) { continue };
const priorValue = game.settings.get(setting.namespace, setting.key, {document: true})?._source.value;
let newSetting;
try {
newSetting = await game.settings.set(setting.namespace, setting.key, value, {document: true});
} catch(error) {
ui.notifications.error(error);
}
if ( priorValue === newSetting?._source.value ) { continue }; // Compare JSON strings
requiresClientReload ||= (setting.scope !== CONST.SETTING_SCOPES.WORLD) && setting.requiresReload;
requiresWorldReload ||= (setting.scope === CONST.SETTING_SCOPES.WORLD) && setting.requiresReload;
}
if ( requiresClientReload || requiresWorldReload ) {
await foundry.applications.settings.SettingsConfig.reloadConfirm({world: requiresWorldReload});
}
};
/** @this {OFTSettingsMenu} */
static async #resetDefaults() {
const form = this.form;
for ( const settingID of this.constructor._SETTINGS ) {
const setting = game.settings.settings.get(settingID);
console.log({ settingID, setting });
const input = form[settingID];
if ( !input || !setting ) { continue };
if ( input.type === `checkbox` ) {
input.checked = setting.default;
}
else {
input.value = setting.default;
};
input.dispatchEvent(new Event(`change`));
}
ui.notifications.info(`SETTINGS.ResetInfo`, {localize: true});
};
// #endregion Actions
};