From 43c630c1f7c02a7b2d14fbe908c2ca15f332552c Mon Sep 17 00:00:00 2001 From: Vassili Minaev Date: Tue, 12 May 2026 18:21:33 -0600 Subject: [PATCH] Port End Session dialogs to DialogV2 for v13/v14 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit V1 Dialog and Dialog.confirm are deprecated in v13 and removed in v14. Migrate the three sites in macros.js (attendance grid, single-session confirm, multi-session pick) to foundry.applications.api.DialogV2, and drop the jQuery used in their callbacks in favor of querySelector + dataset/value on dialog.element. Use rejectClose: false to preserve the prior null-on-close behavior. Bump version to 0.2.0 and widen compatibility to verified 13, max 14 (min stays at 12 — DialogV2 has been available since v12). Co-Authored-By: Claude Opus 4.7 --- module.json | 6 +-- scripts/macros.js | 118 ++++++++++++++++++++++------------------------ 2 files changed, 60 insertions(+), 64 deletions(-) diff --git a/module.json b/module.json index 3e41e19..dd63e2e 100644 --- a/module.json +++ b/module.json @@ -2,11 +2,11 @@ "id": "seitime-bridge", "title": "Seitime Bridge", "description": "Pushes dnd5e character data from Foundry VTT to a Seitime Frappe site at session end. Companion to the st Frappe app.", - "version": "0.1.0", + "version": "0.2.0", "compatibility": { "minimum": "12", - "verified": "12", - "maximum": "13" + "verified": "13", + "maximum": "14" }, "authors": [ { "name": "Vassili" } diff --git a/scripts/macros.js b/scripts/macros.js index 40c241f..ddf5ae4 100644 --- a/scripts/macros.js +++ b/scripts/macros.js @@ -101,45 +101,44 @@ async function showAttendanceDialog(proposal) { }) .join(""); - return new Promise((resolve) => { - new Dialog( + const result = await foundry.applications.api.DialogV2.wait({ + window: { title: "Finalize Attendance" }, + content: ` +

Confirm each player's attendance for this session.

+ + + + + + + + + ${rows} +
PlayerCharacter(s)Status
+ `, + buttons: [ + { action: "cancel", label: "Cancel", callback: () => null }, { - title: "Finalize Attendance", - content: ` -

Confirm each player's attendance for this session.

- - - - - - - - - ${rows} -
PlayerCharacter(s)Status
- `, - buttons: { - cancel: { label: "Cancel", callback: () => resolve(null) }, - confirm: { - label: "Confirm", - callback: (html) => { - const result = []; - html.find("select[data-player]").each(function () { - result.push({ - player: $(this).data("player"), - status: $(this).val(), - }); - }); - resolve(result); - }, - }, + action: "confirm", + label: "Confirm", + default: true, + callback: (_event, _button, dialog) => { + const out = []; + dialog.element.querySelectorAll("select[data-player]").forEach((select) => { + out.push({ + player: select.dataset.player, + status: select.value, + }); + }); + return out; }, - default: "confirm", - close: () => resolve(null), }, - { width: 560 }, - ).render(true); + ], + position: { width: 560 }, + rejectClose: false, }); + + return result ?? null; } /** @@ -167,15 +166,14 @@ export async function pushAllSnapshots() { async function pickSession(sessions) { if (sessions.length === 1) { const s = sessions[0]; - const confirmed = await Dialog.confirm({ - title: "End Session", + const confirmed = await foundry.applications.api.DialogV2.confirm({ + window: { title: "End Session" }, content: `

End ${escapeHtml(s.session_title)}?

This will mark it Completed, schedule the next session, and push snapshots for all PCs.

`, - yes: () => true, - no: () => false, - defaultYes: true, + yes: { default: true }, + rejectClose: false, }); return confirmed ? s.session_id : null; } @@ -187,29 +185,27 @@ async function pickSession(sessions) { ) .join(""); - return new Promise((resolve) => { - new Dialog({ - title: "End Session", - content: ` -

Multiple scheduled sessions match this Foundry world. Pick one to end:

- - `, - buttons: { - cancel: { label: "Cancel", callback: () => resolve(null) }, - end: { - label: "End Session", - callback: (html) => { - const value = html.find("#seitime-session-pick").val(); - resolve(value || null); - }, - }, + const value = await foundry.applications.api.DialogV2.wait({ + window: { title: "End Session" }, + content: ` +

Multiple scheduled sessions match this Foundry world. Pick one to end:

+ + `, + buttons: [ + { action: "cancel", label: "Cancel", callback: () => null }, + { + action: "end", + label: "End Session", + default: true, + callback: (_event, _button, dialog) => + dialog.element.querySelector("#seitime-session-pick")?.value || null, }, - default: "end", - close: () => resolve(null), - }).render(true); + ], + rejectClose: false, }); + return value ?? null; } function summarizeAttendance(attendance) {