FA Embedded Image Viewer

Embeds the clicked Image on the Current Site, so you can view it without loading the submission Page

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

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

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name        FA Embedded Image Viewer
// @namespace   Violentmonkey Scripts
// @match       *://*.furaffinity.net/*
// @require     https://greasyfork.org/scripts/525666-furaffinity-prototype-extensions/code/525666-furaffinity-prototype-extensions.js
// @require     https://greasyfork.org/scripts/483952-furaffinity-request-helper/code/483952-furaffinity-request-helper.js
// @require     https://greasyfork.org/scripts/492931-furaffinity-submission-image-viewer/code/492931-furaffinity-submission-image-viewer.js
// @require     https://greasyfork.org/scripts/485827-furaffinity-match-list/code/485827-furaffinity-match-list.js
// @require     https://greasyfork.org/scripts/485153-furaffinity-loading-animations/code/485153-furaffinity-loading-animations.js
// @require     https://greasyfork.org/scripts/476762-furaffinity-custom-pages/code/476762-furaffinity-custom-pages.js
// @require     https://greasyfork.org/scripts/475041-furaffinity-custom-settings/code/475041-furaffinity-custom-settings.js
// @grant       GM_info
// @version     2.5.6
// @author      Midori Dragon
// @description Embeds the clicked Image on the Current Site, so you can view it without loading the submission Page
// @icon        https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png
// @license     MIT
// @homepageURL https://greasyfork.org/scripts/458971-fa-embedded-image-viewer
// @supportURL  https://greasyfork.org/scripts/458971-fa-embedded-image-viewer/feedback
// ==/UserScript==
// jshint esversion: 11
(function (exports) {
    'use strict';

    class EmbeddedHTML {
        static get html() {
            return `
<div id="eiv-background">
    <a id="eiv-submission-container"></a>
    <div id="eiv-button-container">
        <div id="eiv-button-wrapper">
            <a id="eiv-fav-button" type="button" class="eiv-button button standard mobile-fix">⠀⠀</a>
            <a id="eiv-download-button" type="button" class="eiv-button button standard mobile-fix">Download</a>
            <a id="eiv-open-button" type="button" class="eiv-button button standard mobile-fix">Open</a>
            <a id="eiv-open-gallery-button" type="button" class="eiv-button button standard mobile-fix" style="display: none;">Open Gallery</a>
            <a id="eiv-remove-sub-button" type="button" class="eiv-button button standard mobile-fix" style="display: none;">Remove</a>
            <a id="eiv-close-button" type="button" class="eiv-button button standard mobile-fix">Close</a>
        </div>
        <div id="eiv-preview-spinner-container"></div>
    </div>
    <div id="eiv-additional-info-container">
        <a>by </a>
        <a id="eiv-additional-info">unknown</a>
        <a id="eiv-additional-info-watching"></a>
    </div>
</div>`;
        }
    }

    function getByLinkFromFigcaption(figcaption) {
        if (figcaption != null) {
            const infos = figcaption.querySelectorAll('i');
            let userLink = null;
            for (const info of Array.from(infos)) {
                if (info.textContent?.toLowerCase().includes('by') ?? false) {
                    const linkElem = info.parentNode?.querySelector('a[href][title]');
                    if (linkElem) {
                        userLink = linkElem.getAttribute('href');
                    }
                }
            }
            return userLink;
        }
        return null;
    }
    function getUserFromFigcaption(figcaption) {
        if (figcaption != null) {
            const infos = figcaption.querySelectorAll('i');
            let userLink = null;
            for (const info of Array.from(infos)) {
                if (info.textContent?.toLowerCase().includes('by') ?? false) {
                    const linkElem = info.parentNode?.querySelector('a[href][title]');
                    if (linkElem) {
                        userLink = linkElem.getAttribute('href');
                        userLink = userLink?.trimEnd('/');
                        userLink = userLink?.split('/').pop() ?? null;
                    }
                }
            }
            return userLink;
        }
        return null;
    }
    function getFavKey(doc) {
        // Get the column page element
        const columnPage = doc.getElementById('columnpage');
        // Find the navbar within the column page that contains favorite navigation
        const navbar = columnPage?.querySelector('div[class*="favorite-nav"]');
        // Select all buttons with a href attribute within the navbar
        const buttons = navbar?.querySelectorAll('a[class*="button"][href]') ?? [];
        let favButton;
        // Iterate through the buttons to find the one related to favorites
        for (const button of Array.from(buttons)) {
            if (button.textContent?.toLowerCase().includes('fav') ?? false) {
                favButton = button;
            }
        }
        // If a favorite button is found, extract the favorite key and status
        if (favButton != null) {
            const favKey = favButton.getAttribute('href')?.split('?key=')[1] ?? null;
            const isFav = !(favButton.getAttribute('href')?.toLowerCase().includes('unfav') ?? true);
            return { favKey, isFav };
        }
        // Return null if no favorite button is found
        return null;
    }
    function downloadImage() {
        let url = window.location.toString();
        // If the url contains a query string, remove it
        if (url.includes('?')) {
            const parts = url.split('?');
            url = parts[0];
        }
        // Create an anchor element to download the image
        const download = document.createElement('a');
        download.href = url;
        download.download = url.substring(url.lastIndexOf('/') + 1);
        download.style.display = 'none';
        document.body.appendChild(download);
        download.click();
        document.body.removeChild(download);
        window.close();
    }

    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 = "#eiv-main {\n    position: fixed;\n    width: 100vw;\n    height: 100vh;\n    max-width: 1850px;\n    z-index: 999999;\n    background: rgba(30, 33, 38, .65);\n}\n\n#eiv-background {\n    position: fixed;\n    display: flex;\n    flex-direction: column;\n    left: 50%;\n    transform: translate(-50%, 0%);\n    margin-top: 20px;\n    padding: 20px;\n    background: rgba(30, 33, 38, .90);\n    border-radius: 10px;\n}\n\n#eiv-submission-container {\n    -webkit-user-drag: none;\n}\n\n.eiv-submission-img {\n    max-width: inherit;\n    max-height: inherit;\n    border-radius: 10px;\n    user-select: none;\n}\n\n#eiv-button-container {\n    position: relative;\n    margin-top: 20px;\n    margin-bottom: 6px;\n    margin-left: 20px;\n}\n\n#eiv-button-wrapper {\n    display: flex;\n    justify-content: center;\n    align-items: center;\n}\n\n#eiv-preview-spinner-container {\n    position: absolute;\n    top: 50%;\n    right: 0;\n    transform: translateY(-50%);\n}\n\n.eiv-button {\n    margin-left: 4px;\n    margin-right: 4px;\n    user-select: none;\n}\n\n#eiv-additional-info {\n    color: #afc6e1;\n}\n";
    styleInject(css_248z);

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

    var LogLevel;
    (function (LogLevel) {
        LogLevel[LogLevel["Error"] = 1] = "Error";
        LogLevel[LogLevel["Warning"] = 2] = "Warning";
        LogLevel[LogLevel["Info"] = 3] = "Info";
    })(LogLevel || (LogLevel = {}));
    class Logger {
        static log(logLevel = LogLevel.Warning, ...args) {
            if (window.__FF_GLOBAL_LOG_LEVEL__ == null) {
                window.__FF_GLOBAL_LOG_LEVEL__ = LogLevel.Error;
            }
            if (logLevel > window.__FF_GLOBAL_LOG_LEVEL__) {
                return;
            }
            switch (logLevel) {
                case LogLevel.Error:
                    console.error(...args);
                    break;
                case LogLevel.Warning:
                    console.warn(...args);
                    break;
                case LogLevel.Info:
                    console.log(...args);
                    break;
            }
        }
        static setLogLevel(logLevel) {
            window.__FF_GLOBAL_LOG_LEVEL__ = logLevel;
        }
        static logError(...args) {
            Logger.log(LogLevel.Error, ...args);
        }
        static logWarning(...args) {
            Logger.log(LogLevel.Warning, ...args);
        }
        static logInfo(...args) {
            Logger.log(LogLevel.Info, ...args);
        }
    }

    const embeddedModes = {
        watchesFavoriteViewer: 'wfv-favorites',
    };
    class EmbeddedImage extends EventTarget {
        embeddedElem;
        submissionImg;
        favRequestRunning = false;
        downloadRequestRunning = false;
        faImageViewer;
        _imageLoaded = false;
        _onRemove;
        loadingSpinner;
        previewLoadingSpinner;
        constructor(figure) {
            super();
            Object.setPrototypeOf(this, EmbeddedImage.prototype);
            this.embeddedElem = document.createElement('div');
            this.createElements(figure);
            const submissionContainer = document.getElementById('eiv-submission-container');
            const previewLoadingSpinnerContainer = document.getElementById('eiv-preview-spinner-container');
            this.loadingSpinner = new window.FALoadingSpinner(submissionContainer);
            this.loadingSpinner.delay = loadingSpinSpeedSetting.value;
            this.loadingSpinner.spinnerThickness = 6;
            this.loadingSpinner.visible = true;
            this.previewLoadingSpinner = new window.FALoadingSpinner(previewLoadingSpinnerContainer);
            this.previewLoadingSpinner.delay = loadingSpinSpeedSetting.value;
            this.previewLoadingSpinner.spinnerThickness = 4;
            this.previewLoadingSpinner.size = 40;
            // Add click event to remove the embedded element when clicked outside
            document.addEventListener('click', this.onDocumentClick.bind(this));
            void this.fillSubDocInfos(figure);
            void this.fillUserInfos(figure);
        }
        static get embeddedExists() {
            return document.getElementById('eiv-main') != null;
        }
        get onRemove() {
            return this._onRemove;
        }
        set onRemove(handler) {
            this._onRemove = handler;
        }
        onDocumentClick(event) {
            if (event.target === document.documentElement) {
                this.remove();
            }
        }
        onOpenClick() {
            if (closeEmbedAfterOpenSetting.value) {
                this.remove();
            }
        }
        async onRemoveSubClick(figure) {
            const sid = figure.id.trimStart('sid-');
            this.remove();
            figure.remove();
            await requestHelper.PersonalUserRequests.MessageRequests.NewSubmissions.removeSubmissions([sid]);
        }
        invokeRemove() {
            this._onRemove?.();
            this.dispatchEvent(new Event('remove'));
        }
        remove() {
            this.faImageViewer?.destroy();
            this.embeddedElem.parentNode?.removeChild(this.embeddedElem);
            document.removeEventListener('click', this.onDocumentClick);
            this.invokeRemove();
        }
        createElements(figure) {
            // Create the main container for the embedded element
            this.embeddedElem.id = 'eiv-main';
            this.embeddedElem.setAttribute('eiv-sid', figure.id.trimStart('sid-'));
            this.embeddedElem.innerHTML = EmbeddedHTML.html;
            const ddmenu = document.getElementById('ddmenu');
            ddmenu.appendChild(this.embeddedElem);
            // Add click event to remove the embedded element when clicked outside
            this.embeddedElem.addEventListener('click', (event) => {
                if (event.target === this.embeddedElem) {
                    this.remove();
                }
            });
            // Get the submission container element
            const submissionContainer = document.getElementById('eiv-submission-container');
            // Set target attribute for opening in new tab based on settings
            if (openInNewTabSetting.value) {
                submissionContainer.setAttribute('target', '_blank');
            }
            // Add click event to close the embed after opening, if setting is enabled
            submissionContainer.addEventListener('click', this.onOpenClick.bind(this));
            // Extract user gallery and scraps links from the figure caption
            const userLink = getByLinkFromFigcaption(figure.querySelector('figcaption'));
            if (userLink != null) {
                const galleryLink = userLink.trimEnd('/').replace('user', 'gallery');
                const scrapsLink = userLink.trimEnd('/').replace('user', 'scraps');
                if (!window.location.toString().includes(userLink) && !window.location.toString().includes(galleryLink) && !window.location.toString().includes(scrapsLink)) {
                    const openGalleryButton = document.getElementById('eiv-open-gallery-button');
                    openGalleryButton.style.display = 'block';
                    openGalleryButton.setAttribute('href', galleryLink);
                    if (openInNewTabSetting.value) {
                        openGalleryButton.setAttribute('target', '_blank');
                    }
                    openGalleryButton.addEventListener('click', this.onOpenClick.bind(this));
                }
            }
            const link = figure.querySelector('a[href]')?.getAttribute('href');
            const openButton = document.getElementById('eiv-open-button');
            openButton.setAttribute('href', link ?? '');
            if (openInNewTabSetting.value) {
                openButton.setAttribute('target', '_blank');
            }
            openButton.addEventListener('click', this.onOpenClick.bind(this));
            const closeButton = document.getElementById('eiv-close-button');
            closeButton.addEventListener('click', this.remove.bind(this));
            const embeddedModesValues = Object.values(embeddedModes);
            if (window.location.toString().toLowerCase().includes('msg/submissions') && embeddedModesValues.every(mode => !window.location.toString().toLocaleLowerCase().includes(mode))) {
                const removeSubButton = document.getElementById('eiv-remove-sub-button');
                removeSubButton.style.display = 'block';
                removeSubButton.addEventListener('click', () => void this.onRemoveSubClick(figure));
            }
            const additionalInfo = document.getElementById('eiv-additional-info');
            const figcaption = figure.querySelector('figcaption');
            const userElems = figcaption?.querySelectorAll('a[href*="user/"]');
            const byElem = userElems?.[userElems.length - 1];
            if (byElem != null && additionalInfo != null) {
                additionalInfo.textContent = `${byElem.textContent}`;
                additionalInfo.setAttribute('href', byElem.getAttribute('href') ?? '');
            }
            const previewLoadingSpinnerContainer = document.getElementById('eiv-preview-spinner-container');
            previewLoadingSpinnerContainer.addEventListener('click', () => {
                this.previewLoadingSpinner.visible = false;
            });
        }
        async fillSubDocInfos(figure) {
            const sid = figure.id.split('-')[1];
            const ddmenu = document.getElementById('ddmenu');
            const doc = await requestHelper.SubmissionRequests.getSubmissionPage(sid);
            if (doc != null) {
                this.submissionImg = doc.getElementById('submissionImg');
                const imgSrc = this.submissionImg.src;
                let prevSrc = this.submissionImg.getAttribute('data-preview-src') ?? undefined;
                if (!string.isNullOrWhitespace(prevSrc)) {
                    Logger.logInfo('Preview quality @' + previewQualitySetting.value);
                    prevSrc = prevSrc?.replace('@600', '@' + previewQualitySetting.value);
                }
                const submissionContainer = document.getElementById('eiv-submission-container');
                this.faImageViewer = new window.FAImageViewer(submissionContainer, imgSrc, prevSrc);
                this.faImageViewer.faImage.imgElem.id = 'eiv-submission-img';
                this.faImageViewer.faImagePreview.imgElem.id = 'eiv-preview-submission-img';
                this.faImageViewer.faImage.imgElem.classList.add('eiv-submission-img');
                this.faImageViewer.faImagePreview.imgElem.classList.add('eiv-submission-img');
                this.faImageViewer.faImage.imgElem.style.maxWidth = this.faImageViewer.faImagePreview.imgElem.style.maxWidth = window.innerWidth - 20 * 2 + 'px';
                this.faImageViewer.faImage.imgElem.style.maxHeight = this.faImageViewer.faImagePreview.imgElem.style.maxHeight = window.innerHeight - ddmenu.clientHeight - 38 * 2 - 20 * 2 - 100 + 'px';
                this.faImageViewer.addEventListener('image-load-start', () => {
                    this._imageLoaded = false;
                });
                this.faImageViewer.addEventListener('image-load', () => {
                    this._imageLoaded = true;
                    this.loadingSpinner.visible = false;
                    this.previewLoadingSpinner.visible = false;
                });
                this.faImageViewer.addEventListener('preview-image-load', () => {
                    this.loadingSpinner.visible = false;
                    if (!this._imageLoaded) {
                        this.previewLoadingSpinner.visible = true;
                    }
                });
                void this.faImageViewer.load();
                const url = doc.querySelector('meta[property="og:url"]')?.getAttribute('content');
                submissionContainer.setAttribute('href', url ?? '');
                const result = getFavKey(doc);
                const favButton = document.getElementById('eiv-fav-button');
                if (result == null) {
                    favButton.style.display = 'none';
                }
                else {
                    favButton.textContent = result.isFav ? '+Fav' : '-Fav';
                    favButton.setAttribute('isFav', result.isFav.toString());
                    favButton.setAttribute('key', result.favKey ?? '');
                    favButton.addEventListener('click', () => {
                        if (!this.favRequestRunning) {
                            void this.doFavRequest(sid);
                        }
                    });
                }
                const downloadButton = document.getElementById('eiv-download-button');
                downloadButton.addEventListener('click', () => {
                    if (this.downloadRequestRunning) {
                        return;
                    }
                    this.downloadRequestRunning = true;
                    const loadingTextSpinner = new window.FALoadingTextSpinner(downloadButton);
                    loadingTextSpinner.delay = loadingSpinSpeedFavSetting.value;
                    loadingTextSpinner.visible = true;
                    const iframe = document.createElement('iframe');
                    iframe.style.display = 'none';
                    iframe.src = this.submissionImg.src + '?eiv-download';
                    iframe.addEventListener('load', () => {
                        this.downloadRequestRunning = false;
                        loadingTextSpinner.visible = false;
                        setTimeout(() => iframe.parentNode?.removeChild(iframe), 100);
                    });
                    document.body.appendChild(iframe);
                });
            }
        }
        async fillUserInfos(figure) {
            if (showWatchingInfoSetting.value) {
                const additionalInfoWatching = document.getElementById('eiv-additional-info-watching');
                const figcaption = figure.querySelector('figcaption');
                if (figcaption != null && additionalInfoWatching != null) {
                    const userLink = getUserFromFigcaption(figcaption);
                    console.log(userLink);
                    if (userLink != null) {
                        const userPage = await requestHelper.UserRequests.getUserPage(userLink);
                        if (userPage != null) {
                            const siteContent = userPage.getElementById('site-content');
                            const navInterfaceButtons = siteContent?.querySelector('userpage-nav-interface-buttons');
                            if (navInterfaceButtons != null) {
                                const watchButton = navInterfaceButtons?.querySelector('a[href^="/watch/"]');
                                console.log(watchButton?.outerHTML);
                                if (watchButton == null) {
                                    additionalInfoWatching.textContent = ' (watching)';
                                }
                                else {
                                    additionalInfoWatching.textContent = ' (not watching)';
                                }
                            }
                        }
                    }
                }
            }
        }
        async doFavRequest(sid) {
            const favButton = document.getElementById('eiv-fav-button');
            // Set the favorite request running flag to true
            this.favRequestRunning = true;
            // Create a loading spinner for the favorite button
            const loadingTextSpinner = new window.FALoadingTextSpinner(favButton);
            loadingTextSpinner.delay = loadingSpinSpeedFavSetting.value;
            loadingTextSpinner.visible = true;
            // Get the favorite key and status from the favorite button
            let favKey = favButton.getAttribute('key') ?? '';
            let isFav = favButton.getAttribute('isFav') === 'true';
            if (string.isNullOrWhitespace(favKey)) {
                favButton.textContent = 'x';
                return;
            }
            if (isFav) {
                // Send the favorite request to the server
                favKey = await requestHelper.SubmissionRequests.favSubmission(sid, favKey) ?? '';
                loadingTextSpinner.visible = false;
                // If the request was successful, set the favorite status to false and update the button text
                if (!string.isNullOrWhitespace(favKey)) {
                    favButton.setAttribute('key', favKey);
                    isFav = false;
                    favButton.setAttribute('isFav', isFav.toString());
                    favButton.textContent = '-Fav';
                }
                else {
                    // If the request was not successful, set the button text to "x" and restore the original text after a short delay
                    favButton.textContent = 'x';
                    setTimeout(() => favButton.textContent = '+Fav', 1000);
                }
            }
            else {
                // Send the unfavorite request to the server
                favKey = await requestHelper.SubmissionRequests.unfavSubmission(sid, favKey) ?? '';
                loadingTextSpinner.visible = false;
                // If the request was successful, set the favorite status to true and update the button text
                if (!string.isNullOrWhitespace(favKey)) {
                    favButton.setAttribute('key', favKey);
                    isFav = true;
                    favButton.setAttribute('isFav', isFav.toString());
                    favButton.textContent = '+Fav';
                }
                else {
                    // If the request was not successful, set the button text to "x" and restore the original text after a short delay
                    favButton.textContent = 'x';
                    setTimeout(() => favButton.textContent = '-Fav', 1000);
                }
            }
            // Set the favorite request running flag back to false
            this.favRequestRunning = false;
        }
        static async addEmbeddedEventForAllFigures() {
            const nonEmbeddedFigures = document.querySelectorAll('figure:not([embedded])') ?? [];
            for (const figure of Array.from(nonEmbeddedFigures)) {
                // Set the attribute to mark this element as embedded
                figure.setAttribute('embedded', 'true');
                // Add the event listener to the figure element
                figure.addEventListener('click', (event) => {
                    // If the event is a mouse event and the target is an HTML element
                    if (event instanceof MouseEvent && event.target instanceof HTMLElement) {
                        // If the event is not a Ctrl+Click event and the target is not a favorite button
                        // and the target is not a checkbox
                        if (!event.ctrlKey && !event.target.id.includes('favbutton') && event.target.getAttribute('type') !== 'checkbox') {
                            // If the target has a href attribute, return
                            if (!string.isNullOrWhitespace(event.target.getAttribute('href'))) {
                                return;
                            }
                            // Prevent the default action of the event
                            event.preventDefault();
                            // If an embedded image viewer does not exist, create one
                            if (!EmbeddedImage.embeddedExists && figure instanceof HTMLElement) {
                                new EmbeddedImage(figure);
                            }
                        }
                    }
                });
            }
        }
    }

    const scriptName = 'FA Embedded Image Viewer';
    const customSettings = new window.FACustomSettings('Furaffinity Features Settings', `${scriptName} Settings`);
    const openInNewTabSetting = customSettings.newSetting(window.FASettingType.Boolean, 'Open in new Tab');
    openInNewTabSetting.description = 'Wether to open links in a new Tab or the current one.';
    openInNewTabSetting.defaultValue = true;
    const loadingSpinSpeedFavSetting = customSettings.newSetting(window.FASettingType.Number, 'Fav Loading Animation');
    loadingSpinSpeedFavSetting.description = 'The duration that the loading animation, for faving a submission, takes for a full rotation in milliseconds.';
    loadingSpinSpeedFavSetting.defaultValue = 600;
    const loadingSpinSpeedSetting = customSettings.newSetting(window.FASettingType.Number, 'Embedded Loading Animation');
    loadingSpinSpeedSetting.description = 'The duration that the loading animation of the Embedded element to load takes for a full rotation in milliseconds.';
    loadingSpinSpeedSetting.defaultValue = 1000;
    const closeEmbedAfterOpenSetting = customSettings.newSetting(window.FASettingType.Boolean, 'Close Embed after open');
    closeEmbedAfterOpenSetting.description = 'Wether to close the current embedded Submission after it is opened in a new Tab (also for open Gallery).';
    closeEmbedAfterOpenSetting.defaultValue = true;
    const previewQualitySetting = customSettings.newSetting(window.FASettingType.Option, 'Preview Quality');
    previewQualitySetting.description = 'The quality of the preview image. (Higher values will be slower)';
    previewQualitySetting.defaultValue = 400;
    previewQualitySetting.options = {
        200: 'Very Low (200px)',
        300: 'Low (300px)',
        400: 'Medium (400px)',
        500: 'High (500px)',
        600: 'Very High (600px)'
    };
    const showWatchingInfoSetting = customSettings.newSetting(window.FASettingType.Boolean, 'Show Watching Info');
    showWatchingInfoSetting.description = 'Wether to show if the user is watching the Submissions Author. (Will be slower)';
    showWatchingInfoSetting.defaultValue = false;
    customSettings.loadSettings();
    const requestHelper = new window.FARequestHelper(2);
    if (customSettings.isFeatureEnabled) {
        const matchList = new window.FAMatchList(customSettings);
        matchList.matches = ['net/browse', 'net/user', 'net/gallery', 'net/search', 'net/favorites', 'net/scraps', 'net/controls/favorites', 'net/controls/submissions', 'net/msg/submissions', 'd.furaffinity.net'];
        matchList.runInIFrame = true;
        if (matchList.hasMatch) {
            const page = new window.FACustomPage('d.furaffinity.net', 'eiv-download');
            let pageDownload = false;
            page.addEventListener('onOpen', () => {
                downloadImage();
                pageDownload = true;
            });
            page.checkPageOpened();
            if (!pageDownload && !matchList.isWindowIFrame) {
                void EmbeddedImage.addEmbeddedEventForAllFigures();
                window.addEventListener('ei-update-embedded', () => {
                    void EmbeddedImage.addEmbeddedEventForAllFigures();
                });
            }
        }
    }

    exports.closeEmbedAfterOpenSetting = closeEmbedAfterOpenSetting;
    exports.loadingSpinSpeedFavSetting = loadingSpinSpeedFavSetting;
    exports.loadingSpinSpeedSetting = loadingSpinSpeedSetting;
    exports.openInNewTabSetting = openInNewTabSetting;
    exports.previewQualitySetting = previewQualitySetting;
    exports.requestHelper = requestHelper;
    exports.scriptName = scriptName;
    exports.showWatchingInfoSetting = showWatchingInfoSetting;

    return exports;

})({});