DualityDiceRoller/scripts/dr-button.js

103 lines
3.9 KiB
JavaScript

/**
* DR Quick Button — Foundry VTT v13
* Adds a button near the chat dice/controls that runs the `/dr` command.
*/
Hooks.once("init", () => {
console.log("DR Quick Button | Initializing");
});
// Sidebar chat
Hooks.on("renderChatLog", (app, html) => addDRButton(html));
// Mini/Popout chat
Hooks.on("renderChatPopout", (app, html) => addDRButton(html));
/**
* Adds the DR button to the chat controls
* @param {HTMLElement|jQuery} html - The application HTML
*/
function addDRButton(html) {
if (!html) return;
try {
// Handle both jQuery (legacy) and HTMLElement (v14/AppV2)
const root = html instanceof HTMLElement ? html : html[0];
if (!root) return;
console.debug("DR Quick Button | addDRButton called. Root element:", root.tagName, root.className, root.getAttribute("data-application-part"));
// Common selectors for chat controls/roll privacy across versions
const targetSelectors = [
"#message-modes", // Foundry v14+ (Split button container)
"#chat-controls", // Generic chat controls
"#roll-privacy", // Legacy ID
".roll-privacy", // Legacy class
".roll-type-select", // System specific
".chat-controls" // Generic fallback
];
let found = false;
for (const selector of targetSelectors) {
// Find targets within the root, or check if the root itself is the target
let targets = Array.from(root.querySelectorAll(selector));
if (root.matches && root.matches(selector)) targets.push(root);
// Fallback: If not found in the provided root part, search the whole document
// (In v14, the hook might pass only one part of the ApplicationV2)
if (targets.length === 0) {
const globalTargets = document.querySelectorAll(selector);
// Only consider global targets that are actually visible/relevant
targets = Array.from(globalTargets).filter(t => root.contains(t) || t.closest(".window-app") === root.closest(".window-app") || t.closest("#sidebar") === root.closest("#sidebar"));
}
if (targets.length === 0) continue;
targets.forEach(div => {
// Avoid duplicates
if (div.querySelector(".dr-quick-button-container")) return;
console.log(`DR Quick Button | Adding button to target: ${selector}`);
const container = document.createElement("div");
container.className = "dr-quick-button-container";
const btn = document.createElement("button");
btn.type = "button";
btn.className = "ui-control icon fa-solid dr-quick-button";
btn.title = "Duality Dice Roll";
btn.setAttribute("aria-label", "Duality Dice Roll");
// Use the Daggerheart system icon
btn.innerHTML = `<img src="systems/daggerheart/assets/icons/dice/duality/Daggerheart Foundry_g489.png" alt="DR" style="width:12px; height:16px;">`;
btn.addEventListener("click", async (event) => {
event.preventDefault();
await runDRCommand();
});
container.appendChild(btn);
div.appendChild(container);
found = true;
});
if (found) break;
}
if (!found) {
console.debug("DR Quick Button | No suitable target found in root or related containers.");
}
} catch (err) {
console.error("DR Quick Button | addDRButton error:", err);
}
}
/** Run `/dr` as if typed into chat */
async function runDRCommand() {
try {
await ui?.chat?.processMessage("/dr");
} catch (err) {
console.error("DR Quick Button | Failed to send /dr command:", err);
ui.notifications?.warn("Couldn't run /dr automatically. Try typing /dr in chat.");
}
}