refactor: port DS4 dialogs to ApplicationV2
Convert DialogWithListeners and check-factory.js from deprecated Dialog V1 to DialogV2. Replace jQuery with native DOM methods and update button format. Fixes all remaining V1 Application framework deprecation warnings.
This commit is contained in:
parent
bcc263cc5e
commit
1b7b9f1e8e
3 changed files with 165 additions and 58 deletions
|
@ -311,8 +311,8 @@ export class DS4ActorSheet extends foundry.applications.api.DocumentSheetV2 {
|
|||
const item = this.document.items.get(itemId);
|
||||
if (!item) return;
|
||||
|
||||
const confirmed = await Dialog.confirm({
|
||||
title: game.i18n.localize("DS4.DialogDeleteItemTitle"),
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: { title: game.i18n.localize("DS4.DialogDeleteItemTitle") },
|
||||
content: game.i18n.format("DS4.DialogDeleteItemContent", { item: item.name }),
|
||||
defaultYes: false,
|
||||
});
|
||||
|
@ -414,8 +414,8 @@ export class DS4ActorSheet extends foundry.applications.api.DocumentSheetV2 {
|
|||
const effect = this.document.effects.get(effectId);
|
||||
if (!effect) return;
|
||||
|
||||
const confirmed = await Dialog.confirm({
|
||||
title: game.i18n.localize("DS4.DialogDeleteEffectTitle"),
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: { title: game.i18n.localize("DS4.DialogDeleteEffectTitle") },
|
||||
content: game.i18n.format("DS4.DialogDeleteEffectContent", { effect: effect.name }),
|
||||
defaultYes: false,
|
||||
});
|
||||
|
|
|
@ -3,19 +3,129 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @typedef {DialogOptions} DialogWithListenersOptions
|
||||
* @property {(html: JQuery, app: DialogWithListeners) => void} [activateAdditionalListeners] An optional function to attach additional listeners to the dialog
|
||||
* A simple extension to the DialogV2 class that allows attaching additional listeners.
|
||||
*/
|
||||
export class DialogWithListeners extends foundry.applications.api.DialogV2 {
|
||||
constructor(options = {}) {
|
||||
super(options);
|
||||
this.activateAdditionalListeners = options.activateAdditionalListeners;
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: ["dialog", "dialog-with-listeners"],
|
||||
tag: "dialog",
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple extension to the {@link Dialog} class that allows attaching additional listeners.
|
||||
*/
|
||||
export class DialogWithListeners extends Dialog {
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
if (this.options.activateAdditionalListeners !== undefined) {
|
||||
this.options.activateAdditionalListeners(html, this);
|
||||
async _onRender(context, options) {
|
||||
await super._onRender(context, options);
|
||||
|
||||
// Attach additional listeners if provided
|
||||
if (this.activateAdditionalListeners && typeof this.activateAdditionalListeners === 'function') {
|
||||
this.activateAdditionalListeners(this.element, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a confirmation dialog using the V2 framework with additional listeners support
|
||||
* @param {object} options - Dialog options
|
||||
* @param {string} options.title - Dialog title (deprecated, use window.title)
|
||||
* @param {object} options.window - Window configuration
|
||||
* @param {string} options.window.title - Dialog title
|
||||
* @param {string} options.content - Dialog content HTML
|
||||
* @param {boolean} options.defaultYes - Whether "Yes" is the default button
|
||||
* @param {Function} options.activateAdditionalListeners - Function to attach additional listeners
|
||||
* @returns {Promise<boolean>} True if confirmed, false if cancelled
|
||||
*/
|
||||
static async confirm(options = {}) {
|
||||
const { title, window = {}, content, defaultYes = true, activateAdditionalListeners, ...rest } = options;
|
||||
|
||||
// Handle backward compatibility with title parameter
|
||||
if (title && !window.title) {
|
||||
window.title = title;
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const dialog = new DialogWithListeners({
|
||||
window: {
|
||||
title: window.title || "Confirm",
|
||||
...window,
|
||||
},
|
||||
content,
|
||||
activateAdditionalListeners,
|
||||
buttons: [
|
||||
{
|
||||
action: "yes",
|
||||
label: game.i18n.localize("Yes"),
|
||||
icon: "fas fa-check",
|
||||
default: defaultYes,
|
||||
callback: () => resolve(true),
|
||||
},
|
||||
{
|
||||
action: "no",
|
||||
label: game.i18n.localize("No"),
|
||||
icon: "fas fa-times",
|
||||
default: !defaultYes,
|
||||
callback: () => resolve(false),
|
||||
},
|
||||
],
|
||||
close: () => resolve(false),
|
||||
...rest,
|
||||
});
|
||||
|
||||
dialog.render(true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a prompt dialog using the V2 framework with additional listeners support
|
||||
* @param {object} options - Dialog options
|
||||
* @param {string} options.title - Dialog title (deprecated, use window.title)
|
||||
* @param {object} options.window - Window configuration
|
||||
* @param {string} options.window.title - Dialog title
|
||||
* @param {string} options.content - Dialog content HTML
|
||||
* @param {object} options.buttons - Button configuration
|
||||
* @param {Function} options.activateAdditionalListeners - Function to attach additional listeners
|
||||
* @returns {Promise} Promise that resolves with the result
|
||||
*/
|
||||
static async prompt(options = {}) {
|
||||
const { title, window = {}, content, buttons = {}, activateAdditionalListeners, ...rest } = options;
|
||||
|
||||
// Handle backward compatibility with title parameter
|
||||
if (title && !window.title) {
|
||||
window.title = title;
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
// Convert V1 button format to V2 format
|
||||
const v2Buttons = Object.entries(buttons).map(([key, button]) => ({
|
||||
action: key,
|
||||
label: button.label || key,
|
||||
icon: button.icon || "",
|
||||
default: button.default || false,
|
||||
callback: (event) => {
|
||||
const result = button.callback ? button.callback(event) : key;
|
||||
resolve(result);
|
||||
},
|
||||
}));
|
||||
|
||||
const dialog = new DialogWithListeners({
|
||||
window: {
|
||||
title: window.title || "Dialog",
|
||||
...window,
|
||||
},
|
||||
content,
|
||||
activateAdditionalListeners,
|
||||
buttons: v2Buttons,
|
||||
close: () => resolve(null),
|
||||
...rest,
|
||||
});
|
||||
|
||||
dialog.render(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,58 +169,55 @@ async function askForInteractiveRollData(checkTargetNumber, options = {}, { temp
|
|||
const renderedHtml = await foundry.applications.handlebars.renderTemplate(usedTemplate, templateData);
|
||||
|
||||
const dialogPromise = new Promise((resolve) => {
|
||||
new DialogWithListeners(
|
||||
{
|
||||
new DialogWithListeners({
|
||||
window: {
|
||||
title: usedTitle,
|
||||
content: renderedHtml,
|
||||
buttons: {
|
||||
ok: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
||||
callback: (html) => {
|
||||
if (!("jquery" in html)) {
|
||||
throw new Error(
|
||||
getGame().i18n.format("DS4.ErrorUnexpectedHtmlType", {
|
||||
exType: "JQuery",
|
||||
realType: "HTMLElement",
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
const innerForm = html[0]?.querySelector("form");
|
||||
if (!innerForm) {
|
||||
throw new Error(
|
||||
getGame().i18n.format("DS4.ErrorCouldNotFindHtmlElement", {
|
||||
htmlElement: "form",
|
||||
}),
|
||||
);
|
||||
}
|
||||
resolve(innerForm);
|
||||
}
|
||||
},
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: getGame().i18n.localize("DS4.GenericCancelButton"),
|
||||
},
|
||||
content: renderedHtml,
|
||||
buttons: [
|
||||
{
|
||||
action: "ok",
|
||||
icon: "fas fa-check",
|
||||
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
||||
default: true,
|
||||
callback: (event) => {
|
||||
const dialog = event.target.closest("dialog");
|
||||
const innerForm = dialog?.querySelector("form");
|
||||
if (!innerForm) {
|
||||
throw new Error(
|
||||
getGame().i18n.format("DS4.ErrorCouldNotFindHtmlElement", {
|
||||
htmlElement: "form",
|
||||
}),
|
||||
);
|
||||
}
|
||||
resolve(innerForm);
|
||||
},
|
||||
},
|
||||
default: "ok",
|
||||
},
|
||||
{
|
||||
activateAdditionalListeners: (html, app) => {
|
||||
const checkModifierCustomFormGroup = html.find(`#check-modifier-custom-${id}`).parent(".form-group");
|
||||
html.find(`#check-modifier-${id}`).on("change", (event) => {
|
||||
if (event.currentTarget.value === "custom" && checkModifierCustomFormGroup.hasClass("ds4-hidden")) {
|
||||
checkModifierCustomFormGroup.removeClass("ds4-hidden");
|
||||
{
|
||||
action: "cancel",
|
||||
icon: "fas fa-times",
|
||||
label: getGame().i18n.localize("DS4.GenericCancelButton"),
|
||||
callback: () => resolve(null),
|
||||
},
|
||||
],
|
||||
close: () => resolve(null),
|
||||
activateAdditionalListeners: (html, app) => {
|
||||
const checkModifierCustomFormGroup = html.querySelector(`#check-modifier-custom-${id}`)?.closest(".form-group");
|
||||
const checkModifierSelect = html.querySelector(`#check-modifier-${id}`);
|
||||
|
||||
if (checkModifierSelect) {
|
||||
checkModifierSelect.addEventListener("change", (event) => {
|
||||
if (event.currentTarget.value === "custom" && checkModifierCustomFormGroup?.classList.contains("ds4-hidden")) {
|
||||
checkModifierCustomFormGroup.classList.remove("ds4-hidden");
|
||||
app.setPosition({ height: "auto" });
|
||||
} else if (!checkModifierCustomFormGroup.hasClass("ds4-hidden")) {
|
||||
checkModifierCustomFormGroup.addClass("ds4-hidden");
|
||||
} else if (checkModifierCustomFormGroup && !checkModifierCustomFormGroup.classList.contains("ds4-hidden")) {
|
||||
checkModifierCustomFormGroup.classList.add("ds4-hidden");
|
||||
app.setPosition({ height: "auto" });
|
||||
}
|
||||
});
|
||||
},
|
||||
id,
|
||||
}
|
||||
},
|
||||
).render(true);
|
||||
}).render(true);
|
||||
});
|
||||
const dialogForm = await dialogPromise;
|
||||
return parseDialogFormData(dialogForm);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue