Furaffinity-Message-Box

Library to hold MessageBox functions for Furaffinity

Este script no debería instalarse directamente. Es una biblioteca que utilizan otros scripts mediante la meta-directiva de inclusión // @require https://update.greasyfork.org/scripts/528997/1765109/Furaffinity-Message-Box.js

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name        Furaffinity-Message-Box
// @namespace   Violentmonkey Scripts
// @require     https://greasyfork.org/scripts/525666-furaffinity-prototype-extensions/code/525666-furaffinity-prototype-extensions.js
// @grant       GM_info
// @version     1.0.5
// @author      Midori Dragon
// @description Library to hold MessageBox functions for Furaffinity
// @icon        https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png
// @license     MIT
// @homepageURL https://greasyfork.org/scripts/528997-furaffinity-message-box
// @supportURL  https://greasyfork.org/scripts/528997-furaffinity-message-box/feedback
// ==/UserScript==
// jshint esversion: 11
(function () {
    'use strict';

    /**
     * Specifies the buttons that are displayed on a message box.
     * Similar to System.Windows.Forms.MessageBoxButtons in C#.
     */
    var MessageBoxButtons;
    (function (MessageBoxButtons) {
        /**
         * The message box contains an OK button.
         */
        MessageBoxButtons[MessageBoxButtons["OK"] = 0] = "OK";
        /**
         * The message box contains OK and Cancel buttons.
         */
        MessageBoxButtons[MessageBoxButtons["OKCancel"] = 1] = "OKCancel";
        /**
         * The message box contains Abort, Retry, and Ignore buttons.
         */
        MessageBoxButtons[MessageBoxButtons["AbortRetryIgnore"] = 2] = "AbortRetryIgnore";
        /**
         * The message box contains Yes, No, and Cancel buttons.
         */
        MessageBoxButtons[MessageBoxButtons["YesNoCancel"] = 3] = "YesNoCancel";
        /**
         * The message box contains Yes and No buttons.
         */
        MessageBoxButtons[MessageBoxButtons["YesNo"] = 4] = "YesNo";
        /**
         * The message box contains Retry and Cancel buttons.
         */
        MessageBoxButtons[MessageBoxButtons["RetryCancel"] = 5] = "RetryCancel";
    })(MessageBoxButtons || (MessageBoxButtons = {}));

    /**
     * Specifies the icon that is displayed on a message box.
     * Similar to System.Windows.Forms.MessageBoxIcon in C#.
     */
    var MessageBoxIcon;
    (function (MessageBoxIcon) {
        /**
         * No icon is displayed.
         */
        MessageBoxIcon[MessageBoxIcon["None"] = 0] = "None";
        /**
         * An error icon is displayed on the message box.
         */
        MessageBoxIcon[MessageBoxIcon["Error"] = 16] = "Error";
        /**
         * A warning icon is displayed on the message box.
         */
        MessageBoxIcon[MessageBoxIcon["Warning"] = 48] = "Warning";
        /**
         * An information icon is displayed on the message box.
         */
        MessageBoxIcon[MessageBoxIcon["Information"] = 64] = "Information";
        /**
         * A question mark icon is displayed on the message box.
         */
        MessageBoxIcon[MessageBoxIcon["Question"] = 32] = "Question";
    })(MessageBoxIcon || (MessageBoxIcon = {}));

    /**
     * Specifies identifiers to indicate the return value of a dialog box.
     * Similar to System.Windows.Forms.DialogResult in C#.
     */
    var DialogResult;
    (function (DialogResult) {
        /**
         * Nothing is returned from the dialog box. This means that the modal dialog continues running.
         */
        DialogResult[DialogResult["None"] = 0] = "None";
        /**
         * The dialog box return value is OK (usually sent from a button labeled OK).
         */
        DialogResult[DialogResult["OK"] = 1] = "OK";
        /**
         * The dialog box return value is Cancel (usually sent from a button labeled Cancel).
         */
        DialogResult[DialogResult["Cancel"] = 2] = "Cancel";
        /**
         * The dialog box return value is Abort (usually sent from a button labeled Abort).
         */
        DialogResult[DialogResult["Abort"] = 3] = "Abort";
        /**
         * The dialog box return value is Retry (usually sent from a button labeled Retry).
         */
        DialogResult[DialogResult["Retry"] = 4] = "Retry";
        /**
         * The dialog box return value is Ignore (usually sent from a button labeled Ignore).
         */
        DialogResult[DialogResult["Ignore"] = 5] = "Ignore";
        /**
         * The dialog box return value is Yes (usually sent from a button labeled Yes).
         */
        DialogResult[DialogResult["Yes"] = 6] = "Yes";
        /**
         * The dialog box return value is No (usually sent from a button labeled No).
         */
        DialogResult[DialogResult["No"] = 7] = "No";
    })(DialogResult || (DialogResult = {}));

    /**
     * Provides SVG icons for the MessageBox component.
     */
    class MessageBoxIcons {
        /**
         * Gets the SVG icon based on the specified MessageBoxIcon.
         * @param icon The MessageBoxIcon to get the SVG for.
         * @returns The SVG string for the specified icon.
         */
        static getIconSvg(icon) {
            switch (icon) {
                case MessageBoxIcon.Error:
                    return '<svg xmlns="http://www.w3.org/2000/svg" height="32px" viewBox="0 -960 960 960" width="32px" fill="#ff0000"><path d="M480-280q17 0 28.5-11.5T520-320q0-17-11.5-28.5T480-360q-17 0-28.5 11.5T440-320q0 17 11.5 28.5T480-280Zm-40-160h80v-240h-80v240Zm40 360q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>';
                case MessageBoxIcon.Warning:
                    return '<svg xmlns="http://www.w3.org/2000/svg" height="32px" viewBox="0 -960 960 960" width="32px" fill="#ffcc4d"><path d="m40-120 440-760 440 760H40Zm138-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm-40-120h80v-200h-80v200Zm40-100Z"/></svg>';
                case MessageBoxIcon.Information:
                    return '<svg xmlns="http://www.w3.org/2000/svg" height="32px" viewBox="0 -960 960 960" width="32px" fill="#2196f3"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>';
                case MessageBoxIcon.Question:
                    return '<svg xmlns="http://www.w3.org/2000/svg" height="32px" viewBox="0 -960 960 960" width="32px" fill="#2196f3"><path d="M478-240q21 0 35.5-14.5T528-290q0-21-14.5-35.5T478-340q-21 0-35.5 14.5T428-290q0 21 14.5 35.5T478-240Zm-36-154h74q0-33 7.5-52t42.5-52q26-26 41-49.5t15-56.5q0-56-41-86t-97-30q-57 0-92.5 30T342-618l66 26q5-18 22.5-39t53.5-21q32 0 48 17.5t16 38.5q0 20-12 37.5T506-526q-44 39-54 59t-10 73Zm38 314q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>';
                case MessageBoxIcon.None:
                default:
                    return '';
            }
        }
    }

    /**
     * Specifies the theme that is used for the message box.
     */
    var MessageBoxThemes;
    (function (MessageBoxThemes) {
        /**
         * Dark theme with white text and dark gray buttons.
         */
        MessageBoxThemes["Dark"] = "dark";
        /**
         * Aurora theme with white text and medium gray buttons.
         */
        MessageBoxThemes["Aurora"] = "aurora";
        /**
         * Retro theme with white text and medium blue-gray buttons.
         */
        MessageBoxThemes["Retro"] = "retro";
        /**
         * Slate theme with white text and light gray buttons.
         */
        MessageBoxThemes["Slate"] = "slate";
        /**
         * Light theme with black text and light gray buttons.
         */
        MessageBoxThemes["Light"] = "light";
    })(MessageBoxThemes || (MessageBoxThemes = {}));

    function styleInject(css, ref) {
      if ( ref === void 0 ) ref = {};
      var insertAt = ref.insertAt;

      if (typeof document === 'undefined') { return; }

      var head = document.head || document.getElementsByTagName('head')[0];
      var style = document.createElement('style');
      style.type = 'text/css';

      if (insertAt === 'top') {
        if (head.firstChild) {
          head.insertBefore(style, head.firstChild);
        } else {
          head.appendChild(style);
        }
      } else {
        head.appendChild(style);
      }

      if (style.styleSheet) {
        style.styleSheet.cssText = css;
      } else {
        style.appendChild(document.createTextNode(css));
      }
    }

    var css_248z = "/* Base styles */\n.message-box-overlay {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    background-color: rgba(0, 0, 0, 0.5);\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    z-index: 99999999;\n}\n\n/* Dark theme (default) */\n.message-box-container {\n    border: 1px solid #444;\n    border-radius: 5px;\n    padding: 20px;\n    max-width: 500px;\n    width: 100%;\n    font-family: Arial, sans-serif;\n    transition: background-color 0.3s, color 0.3s, border-color 0.3s, box-shadow 0.3s;\n}\n\n.message-box-header {\n    display: flex;\n    align-items: center;\n    margin-bottom: 15px;\n}\n\n.message-box-icon-container {\n    margin-right: 15px;\n    width: 32px;\n    height: 32px;\n    flex-shrink: 0;\n}\n\n.message-box-title {\n    font-size: 18px;\n    font-weight: bold;\n    margin: 0;\n    transition: color 0.3s;\n}\n\n.message-box-content {\n    margin-bottom: 20px;\n    line-height: 1.5;\n    transition: color 0.3s;\n}\n\n.message-box-button-container {\n    display: flex;\n    justify-content: flex-end;\n    gap: 10px;\n}\n\n.message-box-button {\n    padding: 8px 16px;\n    border: none;\n    border-radius: 4px;\n    cursor: pointer;\n    font-size: 14px;\n    font-weight: bold;\n    background-color: #f1efeb;\n    transition: background-color 0.2s, color 0.2s, border-color 0.2s;\n}\n\n.message-box-button:hover {\n    background-color: #e0ded8;\n}\n\n/* Theme: Dark */\nbody[class*=\"theme-dark\"] .message-box-container {\n    background-color: #353b45;\n    border-color: #444;\n    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);\n}\n\nbody[class*=\"theme-dark\"] .message-box-button {\n    background-color: #434b5b;\n}\n\nbody[class*=\"theme-dark\"] .message-box-button:hover {\n    background-color: #576175;\n}\n\n/* Theme: Aurora */\nbody[class*=\"theme-aurora\"] .message-box-container {\n    background-color: #262931;\n    border-color: #444;\n    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);\n}\n\nbody[class*=\"theme-aurora\"] .message-box-button {\n    background-color: #65707c;\n}\n\nbody[class*=\"theme-aurora\"] .message-box-button:hover {\n    background-color: #8692a0;\n}\n\n/* Theme: Retro */\nbody[class*=\"theme-retro\"] .message-box-container {\n    background-color: #2e3b41;\n    border-color: #444;\n    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);\n}\n\nbody[class*=\"theme-retro\"] .message-box-button {\n    background-color: #4c585e;\n}\n\nbody[class*=\"theme-retro\"] .message-box-button:hover {\n    background-color: #7b909a;\n}\n\n/* Theme: Slate */\nbody[class*=\"theme-slate\"] .message-box-container {\n    background-color: #202225;\n    border-color: #444;\n    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);\n}\n\nbody[class*=\"theme-slate\"] .message-box-button {\n    background-color: #8c8c8c;\n}\n\nbody[class*=\"theme-slate\"] .message-box-button:hover {\n    background-color: #b3b1b1;\n}\n\n/* Theme: Light - already defined in base styles */\nbody[class*=\"theme-light\"] .message-box-container {\n    background-color: #f7f7f7;\n    border-color: #ccc;\n    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);\n}\n\nbody[class*=\"theme-light\"] .message-box-button {\n    background-color: #f1efeb;\n}\n\nbody[class*=\"theme-light\"] .message-box-button:hover {\n    background-color: #f1ede7;\n}";
    styleInject(css_248z);

    class string {
        static isNullOrWhitespace(str) {
            return str == null || str.trim() === '';
        }
        static isNullOrEmpty(str) {
            return str == null || str === '';
        }
    }

    class MessageBox {
        static overlay = null;
        static container = null;
        static result = DialogResult.None;
        static resolvePromise = null;
        static currentTheme = MessageBoxThemes.Light;
        /**
         * Gets the current theme.
         * @returns The current theme.
         */
        static getTheme() {
            return this.currentTheme;
        }
        /**
         * Shows a message box with the specified text, caption, buttons, and icon.
         * @param text The text to display in the message box.
         * @param caption The text to display in the title bar of the message box.
         * @param buttons One of the MessageBoxButtons values that specifies which buttons to display in the message box.
         * @param icon One of the MessageBoxIcon values that specifies which icon to display in the message box.
         * @returns A DialogResult value that indicates which button was clicked.
         */
        static async show(text, caption = '', buttons = MessageBoxButtons.OK, icon = MessageBoxIcon.None) {
            // Create a promise that will be resolved when a button is clicked
            return new Promise((resolve) => {
                this.resolvePromise = resolve;
                try {
                    this.createMessageBox(text, caption, buttons, icon);
                }
                catch (error) {
                    const reason = error instanceof Error ? error.message : String(error);
                    const fallback = this.getFallbackResult(buttons);

                    alert(`MessageBox failed to display (${reason})\n\n[${caption}]\n${text}`);
                    this.resolvePromise = null;
                    resolve(fallback);
                }
            });
        }
        /**
         * Returns the strongest negating DialogResult for the given button set,
         * used as a fallback when the message box cannot be shown.
         */
        static getFallbackResult(buttons) {
            switch (buttons) {
                case MessageBoxButtons.OK:
                    return DialogResult.OK;
                case MessageBoxButtons.OKCancel:
                    return DialogResult.Cancel;
                case MessageBoxButtons.AbortRetryIgnore:
                    return DialogResult.Abort;
                case MessageBoxButtons.YesNoCancel:
                    return DialogResult.Cancel;
                case MessageBoxButtons.YesNo:
                    return DialogResult.No;
                case MessageBoxButtons.RetryCancel:
                    return DialogResult.Cancel;
                default:
                    return DialogResult.Cancel;
            }
        }
        /**
         * Creates the message box elements and adds them to the DOM.
         */
        static createMessageBox(text, caption, buttons, icon) {
            // Create overlay
            this.overlay = document.createElement('div');
            this.overlay.className = 'message-box-overlay';
            // Create container
            this.container = document.createElement('div');
            this.container.className = 'message-box-container';
            // Create header (icon + title)
            const header = document.createElement('div');
            header.className = 'message-box-header';
            // Add icon if specified
            if (icon !== MessageBoxIcon.None) {
                const iconContainer = document.createElement('div');
                iconContainer.className = 'message-box-icon-container';
                iconContainer.innerHTML = MessageBoxIcons.getIconSvg(icon);
                header.appendChild(iconContainer);
            }
            // Add title if specified
            if (!string.isNullOrWhitespace(caption)) {
                const title = document.createElement('h3');
                title.className = 'message-box-title';
                title.textContent = caption;
                header.appendChild(title);
            }
            // Add header to container if it has children
            if (header.children.length !== 0) {
                this.container.appendChild(header);
            }
            // Add content
            const content = document.createElement('div');
            content.className = 'message-box-content';
            content.textContent = text;
            this.container.appendChild(content);
            // Add buttons
            const buttonContainer = document.createElement('div');
            buttonContainer.className = 'message-box-button-container';
            // Add appropriate buttons based on the MessageBoxButtons enum
            this.addButtons(buttonContainer, buttons);
            this.container.appendChild(buttonContainer);
            this.overlay.appendChild(this.container);
            // Add to DOM
            document.body.appendChild(this.overlay);
        }
        /**
         * Adds the appropriate buttons to the message box based on the MessageBoxButtons enum.
         */
        static addButtons(buttonContainer, buttons) {
            switch (buttons) {
                case MessageBoxButtons.OK:
                    this.createButton(buttonContainer, 'OK', DialogResult.OK);
                    break;
                case MessageBoxButtons.OKCancel:
                    this.createButton(buttonContainer, 'OK', DialogResult.OK);
                    this.createButton(buttonContainer, 'Cancel', DialogResult.Cancel);
                    break;
                case MessageBoxButtons.AbortRetryIgnore:
                    this.createButton(buttonContainer, 'Abort', DialogResult.Abort);
                    this.createButton(buttonContainer, 'Retry', DialogResult.Retry);
                    this.createButton(buttonContainer, 'Ignore', DialogResult.Ignore);
                    break;
                case MessageBoxButtons.YesNoCancel:
                    this.createButton(buttonContainer, 'Yes', DialogResult.Yes);
                    this.createButton(buttonContainer, 'No', DialogResult.No);
                    this.createButton(buttonContainer, 'Cancel', DialogResult.Cancel);
                    break;
                case MessageBoxButtons.YesNo:
                    this.createButton(buttonContainer, 'Yes', DialogResult.Yes);
                    this.createButton(buttonContainer, 'No', DialogResult.No);
                    break;
                case MessageBoxButtons.RetryCancel:
                    this.createButton(buttonContainer, 'Retry', DialogResult.Retry);
                    this.createButton(buttonContainer, 'Cancel', DialogResult.Cancel);
                    break;
            }
        }
        /**
         * Creates a button element with the specified text and result.
         */
        static createButton(container, text, result) {
            const button = document.createElement('button');
            button.className = 'message-box-button';
            button.textContent = text;
            // Add click handler
            button.addEventListener('click', () => {
                this.close(result);
            });
            container.appendChild(button);
        }
        /**
         * Closes the message box and resolves the promise with the specified result.
         */
        static close(result) {
            this.result = result;
            // Remove from DOM
            if (this.overlay != null) {
                document.body.removeChild(this.overlay);
                this.overlay = null;
                this.container = null;
            }
            // Resolve the promise
            if (this.resolvePromise != null) {
                this.resolvePromise(result);
                this.resolvePromise = null;
            }
        }
    }

    Object.defineProperties(window, {
        FAMessageBox: { get: () => MessageBox },
        FAMessageBoxButtons: { get: () => MessageBoxButtons },
        FAMessageBoxIcon: { get: () => MessageBoxIcon },
        FADialogResult: { get: () => DialogResult },
    });
    let themeClassName = 'dark';
    const themeStylesheets = document.head.querySelectorAll('link[rel="stylesheet"][href]') ?? [];
    for (const themeStylesheet of Array.from(themeStylesheets)) {
        const themePath = themeStylesheet.getAttribute('href')?.toLowerCase() ?? '';
        if (themePath.includes('dark')) {
            themeClassName = 'dark';
        }
        else if (themePath.includes('aurora')) {
            themeClassName = 'aurora';
        }
        else if (themePath.includes('retro')) {
            themeClassName = 'retro';
        }
        else if (themePath.includes('slate')) {
            themeClassName = 'slate';
        }
        else if (themePath.includes('light')) {
            themeClassName = 'light';
        }
    }
    document.body.classList.add(`theme-${themeClassName}`);

})();