Add notification and submission tracking for the QueryManager

This commit is contained in:
Oliver 2025-11-08 19:07:01 -07:00
parent bd301d69fb
commit 723bcf8735
2 changed files with 40 additions and 14 deletions

View file

@ -34,6 +34,7 @@
}, },
"notifs": { "notifs": {
"error": { "error": {
"missing-id": "An ID must be provided",
"invalid-socket": "Invalid socket data received, this means a module or system bug is present.", "invalid-socket": "Invalid socket data received, this means a module or system bug is present.",
"unknown-socket-event": "An unknown socket event was received: {event}", "unknown-socket-event": "An unknown socket event was received: {event}",
"malformed-socket-payload": "Socket event \"{event}\" received with malformed payload. Details: {details}" "malformed-socket-payload": "Socket event \"{event}\" received with malformed payload. Details: {details}"

View file

@ -1,13 +1,24 @@
/** /**
* @typedef Apple * @typedef QueryData
* @property {string[]} users * @property {string[]} users
* @property {Function} resolve * @property {Function} resolve
* @property {Record<string, object>} responses * @property {Record<string, object>} responses
* @property {(() => Promise<void>)|null} onSubmit
*/ */
const { randomID } = foundry.utils; import { filePath } from "../consts.mjs";
async function sendBasicNotification(userID, answers) {
const content = await foundry.applications.handlebars.renderTemplate(
filePath(`templates/query-response.hbs`),
{ answers },
);
QueryManager.notify(userID, content, { includeGM: false });
};
export class QueryManager { export class QueryManager {
/** @type {Map<string, QueryData>} */
static #queries = new Map(); static #queries = new Map();
static #promises = new Map(); static #promises = new Map();
@ -15,8 +26,18 @@ export class QueryManager {
return this.#queries.has(requestID); return this.#queries.has(requestID);
}; };
static async query(request, users = null, config = undefined) { static async query(
request.id ??= randomID(); request,
{
onSubmit = sendBasicNotification,
users = null,
config = undefined,
} = {},
) {
if (!request.id) {
ui.notifications.error(game.i18n.localize(`taf.notifs.error.missing-id`));
return;
};
game.socket.emit(`system.taf`, { game.socket.emit(`system.taf`, {
event: `query.prompt`, event: `query.prompt`,
@ -39,32 +60,36 @@ export class QueryManager {
users: users ?? game.users.filter(u => u.id !== game.user.id), users: users ?? game.users.filter(u => u.id !== game.user.id),
resolve, resolve,
responses: {}, responses: {},
onSubmit,
}, },
); );
}); });
return promise; return promise;
}; };
static async submit(requestID, answers) {
game.socket.emit(`system.taf`, {
event: `query.submit`,
payload: {
id: requestID,
answers,
},
});
};
static async addResponse(requestID, userID, answers) { static async addResponse(requestID, userID, answers) {
const data = this.#queries.get(requestID); const data = this.#queries.get(requestID);
data.responses[userID] = answers; data.responses[userID] = answers;
await data.onSubmit?.(userID, answers);
// Validate for responses from everyone // Validate for responses from everyone
if (data.users.length === Object.keys(data.responses).length) { if (data.users.length === Object.keys(data.responses).length) {
data.resolve(data.responses); data.resolve(data.responses);
}; };
}; };
static async notify(userID, content, { includeGM = false } = {}) {
game.socket.emit(`system.taf`, {
event: `query.notify`,
payload: {
userID,
content,
includeGM,
},
});
}
static async cancel(requestID) { static async cancel(requestID) {
// prevent cancelling other people's queries // prevent cancelling other people's queries
if (!this.#queries.has(requestID)) { return }; if (!this.#queries.has(requestID)) { return };