/* * This files separates the form-specific validation, creation and types, * so they can be used in the main module. */ import { get_existing_senders } from "./utils.mjs"; const sender_hints_id = "sender_hints" /** * @typedef {Object} MessageFormResponse * @property {string[]} recipients The list of player IDs the message will be sent to * @property {string} sender The name to display as the origin of the message, and in the history * @property {string} message The body of the message, a string of HTML */ /** * @typedef {Object} DialogFormResponse * @property {boolean} valid Is the response valid ? * @property {MessageFormResponse} form_response The response form the dialog form */ /** * Generate the HTML for a whose options are the provided senders. * @param {String} hints_id The ID to use for the providing the hints * @param {String[]} senders The list of existing senders, or an empty string if invalid. */ function generate_sender_hints(hints_id, senders) { // Both arguments need to be usable to generate something useful. if (!hints_id || !senders || senders.length === 0) { return ""; } let sender_hints_html = `` for (let sender of senders) { sender_hints_html += `"; } /** * Given that "required" does not seem to have much impact, check that everything * has been properly filled. * To be able to reopen the dialog with the existing inputs, return the result of the check * as well as the input data. * @param {MessageFormResponse} form_response The response from the form, pre-processed * @return {DialogFormResponse} Pass the response through and a validity flag */ export function validate_form(form_response) { let valid = true; if (form_response.message.length === 0 || form_response.recipients.length === 0 || form_response.sender.length === 0) { ui.notifications.warn("MM.Errors.MissingFields", {localize:true}); valid = false; } return {valid, form_response}; } /** * Prepare the HTML used for the sending message dialog, filling previous values and handling if it is a chained message. * @param {MessageFormResponse|null} [existing_values=null] Values from a previously filled form * @param {boolean} [chain=false] If this is a chained message or not * @returns {string} HTML for the send message Dialog content */ export function prepare_send_message_html(existing_values = null, chain = false) { let players_options = [] for (let user of game.users.players) { players_options.push({ label: user.character ? user.character.name : user.name, value: user.id, }) } if (existing_values && existing_values.recipients.length > 0) { players_options .filter((option) => existing_values.recipients.includes(option.value)) .forEach((option) => {option.selected = true}) } const recipient_input = foundry.applications.fields.createMultiSelectInput({ name: "recipients_IDs", required: true, blank: false, options: players_options, /* * Send chained messages to the same recipients, disallow changing it in this case. * This is an arbitrary decision that simplifies the process of sending the messages. */ disabled: chain, }) const recipient_group = foundry.applications.fields.createFormGroup({ input: recipient_input, label: "MM.Dialogs.SendDialog.RecipientsLabel", hint: chain ? "MM.Dialogs.SendDialog.RecipientsChainHint" : "MM.Dialogs.SendDialog.RecipientsHint", localize: true, }) const sender_input = foundry.applications.fields.createTextInput({ name: "sender_name", required: true, placeholder: game.i18n.localize("MM.Dialogs.SendDialog.SenderPlaceholder"), value: existing_values ? existing_values.sender : null, }) const sender_group = foundry.applications.fields.createFormGroup({ input: sender_input, label: "MM.Dialogs.SendDialog.SenderLabel", hint: "MM.Dialogs.SendDialog.SenderHint", localize: true }) /* * If we can find previous senders in player's histories, create a datalist * with them so that the names can appear as autocompletion when filling the form. */ /* * TODO: This is very silly : it re-computes everything for every form that is opened. * Find a way to cache it or store the senders list it explicitly rather than deduce it * from the history. */ let existing_senders = get_existing_senders(); if (existing_senders.length > 0) { sender_input.setAttribute("list", sender_hints_id) // This keeps the datalist withing the input group as proper HTML. sender_group.insertAdjacentHTML("beforeend", generate_sender_hints(sender_hints_id, existing_senders)) } const message_input = foundry.applications.elements.HTMLProseMirrorElement.create({ name: "message", required: true, value: existing_values && existing_values.message ? existing_values.message : "", editable: true, compact: true, collaborate: false, toggled: false, height: 350, }) const message_group = foundry.applications.fields.createFormGroup({ input: message_input, label: "MM.Dialogs.SendDialog.MessageEditorLabel", stacked: true, localize: true, }) return recipient_group.outerHTML + sender_group.outerHTML + message_group.outerHTML; }