FA Webcomic Auto Loader

Gives you the option to load all the subsequent comic pages on a FurAffinity comic page automatically. Even for pages without given Links

Versión del día 3/2/2025. Echa un vistazo a la versión más reciente.

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        FA Webcomic Auto Loader
// @namespace   Violentmonkey Scripts
// @match       *://*.furaffinity.net/*
// @require     https://update.greasyfork.org/scripts/525666/1530872/Furaffinity-Prototype-Extensions.js
// @require     https://update.greasyfork.org/scripts/483952/1530883/Furaffinity-Request-Helper.js
// @require     https://update.greasyfork.org/scripts/485827/1530881/Furaffinity-Match-List.js
// @require     https://update.greasyfork.org/scripts/485153/1530882/Furaffinity-Loading-Animations.js
// @require     https://update.greasyfork.org/scripts/475041/1531083/Furaffinity-Custom-Settings.js
// @grant       GM_info
// @version     2.1.2
// @author      Midori Dragon
// @description Gives you the option to load all the subsequent comic pages on a FurAffinity comic page automatically. Even for pages without given Links
// @icon        https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png
// @license     MIT
// ==/UserScript==
// jshint esversion: 8
(() => {
    "use strict";
    var LogLevel, __webpack_require__ = {
        d: (exports, definition) => {
            for (var key in definition) if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
                enumerable: true,
                get: definition[key]
            });
        },
        o: (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
    };
    __webpack_require__.d({}, {
        KS: () => backwardSearchSetting,
        _d: () => loadingSpinSpeedSetting,
        WE: () => overwriteNavButtonsSetting,
        uL: () => requestHelper,
        vD: () => scriptName,
        iT: () => useCustomLightboxSetting
    });
    function checkTags(element) {
        var _a;
        if (!("1" === document.body.getAttribute("data-user-logged-in"))) {
            setBlockedState(element, false);
            return;
        }
        const tagsHideMissingTags = "1" === document.body.getAttribute("data-tag-blocklist-hide-tagless"), tags = null === (_a = element.getAttribute("data-tags")) || void 0 === _a ? void 0 : _a.trim().split(/\s+/);
        let blockReason = "";
        if (null != tags && tags.length > 0 && "" !== tags[0]) {
            const blockedTags = function getBannedTags(tags) {
                var _a;
                const tagsBlocklist = null !== (_a = document.body.getAttribute("data-tag-blocklist")) && void 0 !== _a ? _a : [];
                let bTags = [];
                if (null == tags || 0 === tags.length) return [];
                for (const tag of tags) for (const blockedTag of tagsBlocklist) if (tag === blockedTag) bTags.push(blockedTag);
                return [ ...new Set(bTags) ];
            }(tags);
            if (blockedTags.length <= 0) setBlockedState(element, false); else {
                setBlockedState(element, true);
                blockReason = "Blocked tags:\n";
                for (const tag of blockedTags) blockReason += "• " + tag + "\n";
            }
        } else {
            setBlockedState(element, tagsHideMissingTags);
            if (tagsHideMissingTags) blockReason = "Content is missing tags.";
        }
        if ("" !== blockReason && "submissionImg" !== element.id) element.setAttribute("title", blockReason);
    }
    function setBlockedState(element, isBlocked) {
        element.classList[isBlocked ? "add" : "remove"]("blocked-content");
    }
    !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 (null == window.__FF_GLOBAL_LOG_LEVEL__) window.__FF_GLOBAL_LOG_LEVEL__ = LogLevel.Error;
            if (!(logLevel > window.__FF_GLOBAL_LOG_LEVEL__)) switch (logLevel) {
              case LogLevel.Error:
                console.error(...args);
                break;

              case LogLevel.Warning:
                console.warn(...args);
                break;

              case LogLevel.Info:
                console.log(...args);
            }
        }
        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);
        }
    }
    function getDocViewSid(doc) {
        let ogUrl = doc.querySelector('meta[property="og:url"]').getAttribute("content");
        if (null == ogUrl) return -1;
        ogUrl = ogUrl.trimEnd("/");
        return parseInt(ogUrl.split("/").pop());
    }
    const string = class {
        static isNullOrWhitespace(str) {
            return null == str || "" === str.trim();
        }
        static isNullOrEmpty(str) {
            return null == str || "" === str;
        }
    };
    class ComicNavigation {
        constructor(prevId, firstId, nextId) {
            this.prevId = -1;
            this.firstId = -1;
            this.nextId = -1;
            this.prevId = prevId;
            this.firstId = firstId;
            this.nextId = nextId;
        }
        static fromElement(elem) {
            var _a;
            const comicNav = new ComicNavigation(-1, -1, -1), navElems = elem.querySelectorAll('a[href*="view"]');
            if (null == navElems || 0 === navElems.length) return null;
            for (const navElem of Array.from(navElems)) {
                const navText = null === (_a = null == navElem ? void 0 : navElem.textContent) || void 0 === _a ? void 0 : _a.toLowerCase();
                if (string.isNullOrWhitespace(navText)) continue;
                let idText = navElem.getAttribute("href");
                if (!string.isNullOrWhitespace(idText)) {
                    idText = idText.trimEnd("/");
                    idText = idText.split("/").pop();
                    if (navText.includes("prev")) comicNav.prevId = parseInt(idText); else if (navText.includes("next")) comicNav.nextId = parseInt(idText); else if (navText.includes("start") || navText.includes("first")) comicNav.firstId = parseInt(idText);
                }
            }
            return comicNav;
        }
    }
    var __awaiter = function(thisArg, _arguments, P, generator) {
        return new (P || (P = Promise))((function(resolve, reject) {
            function fulfilled(value) {
                try {
                    step(generator.next(value));
                } catch (e) {
                    reject(e);
                }
            }
            function rejected(value) {
                try {
                    step(generator.throw(value));
                } catch (e) {
                    reject(e);
                }
            }
            function step(result) {
                result.done ? resolve(result.value) : function adopt(value) {
                    return value instanceof P ? value : new P((function(resolve) {
                        resolve(value);
                    }));
                }(result.value).then(fulfilled, rejected);
            }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        }));
    };
    class AutoLoaderSearch {
        constructor(rootImg, rootSid, comicNav) {
            this.currImgIndex = 1;
            this.currSid = -1;
            this.rootImg = rootImg;
            this.rootSid = rootSid;
            this.currComicNav = comicNav;
        }
        search() {
            return __awaiter(this, void 0, void 0, (function*() {
                var _a;
                const loadedImgs = {};
                loadedImgs[this.rootSid] = this.rootImg;
                Logger.logInfo(`${scriptName}: starting search...`);
                do {
                    try {
                        if (null == this.currComicNav) break;
                        const img = yield this.getPage(this.currComicNav.nextId);
                        if (null == img) break;
                        if (this.currSid in loadedImgs) break;
                        Logger.logInfo(`${scriptName}: found image with sid '${this.currSid}'`);
                        loadedImgs[this.currSid] = img;
                        this.currImgIndex++;
                    } catch (error) {
                        Logger.logError(error);
                        break;
                    }
                } while (-1 !== (null === (_a = this.currComicNav) || void 0 === _a ? void 0 : _a.nextId));
                Logger.logInfo(`${scriptName}: finished search. Found ${Object.keys(loadedImgs).length} images.`);
                return loadedImgs;
            }));
        }
        getPage(sid) {
            return __awaiter(this, void 0, void 0, (function*() {
                var _a;
                const page = yield requestHelper.SubmissionRequests.getSubmissionPage(sid), img = page.getElementById("submissionImg");
                img.setAttribute("wal-index", this.currImgIndex.toString());
                img.setAttribute("wal-sid", sid.toString());
                this.currSid = getDocViewSid(page);
                const descriptionElem = null === (_a = page.getElementById("columnpage")) || void 0 === _a ? void 0 : _a.querySelector('div[class*="submission-description"]');
                if (null != descriptionElem) this.currComicNav = ComicNavigation.fromElement(descriptionElem); else this.currComicNav = null;
                return img;
            }));
        }
    }
    function isSubmissionPageInGallery(doc) {
        const columnPage = doc.getElementById("columnpage"), favNav = null == columnPage ? void 0 : columnPage.querySelector('div[class*="favorite-nav"]'), mainGalleryButton = null == favNav ? void 0 : favNav.querySelector('a[title*="submissions"]');
        if (null != mainGalleryButton && mainGalleryButton.href.includes("gallery")) return true; else return false;
    }
    function isSubmissionPageInScraps(doc) {
        const columnPage = doc.getElementById("columnpage"), favNav = null == columnPage ? void 0 : columnPage.querySelector('div[class*="favorite-nav"]'), mainGalleryButton = null == favNav ? void 0 : favNav.querySelector('a[title*="submissions"]');
        if (null != mainGalleryButton && mainGalleryButton.href.includes("scraps")) return true; else return false;
    }
    function getCurrGalleryFolder() {
        const url = window.location.toString().toLowerCase();
        if (!url.includes("gallery") || !url.includes("folder")) return;
        const parts = url.split("/"), folderIdIndex = parts.indexOf("folder") + 1;
        if (folderIdIndex >= parts.length) return;
        const folderId = parts[folderIdIndex];
        return parseInt(folderId);
    }
    function generalizeString(inputString, textToNumbers, removeCommonPhrases, removeSpecialChars, removeNumbers, removeSpaces, removeRoman) {
        let outputString = inputString.toLowerCase();
        if (removeCommonPhrases) {
            const commonPhrases = [ "page", "part", "book", "episode" ];
            outputString = outputString.replace(new RegExp(`(?:^|\\s)(${commonPhrases.join("|")})(?:\\s|$)`, "g"), "");
        }
        if (removeRoman) {
            const roman = [ "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", "xi", "xii", "xiii", "xiv", "xv", "xvi", "xvii", "xviii", "xix", "xx" ];
            outputString = outputString.replace(new RegExp(`(?:^|[^a-zA-Z])(${roman.join("|")})(?:[^a-zA-Z]|$)`, "g"), "");
        }
        if (textToNumbers) {
            const numbers = {
                zero: 0,
                one: 1,
                two: 2,
                three: 3,
                four: 4,
                five: 5,
                six: 6,
                seven: 7,
                eight: 8,
                nine: 9,
                ten: 10,
                eleven: 11,
                twelve: 12,
                thirteen: 13,
                fourteen: 14,
                fifteen: 15,
                sixteen: 16,
                seventeen: 17,
                eighteen: 18,
                nineteen: 19,
                twenty: 20,
                thirty: 30,
                forty: 40,
                fifty: 50,
                sixty: 60,
                seventy: 70,
                eighty: 80,
                ninety: 90,
                hundred: 100
            };
            outputString = outputString.replace(new RegExp(Object.keys(numbers).join("|"), "gi"), (match => numbers[match.toLowerCase()].toString()));
        }
        if (removeSpecialChars) outputString = outputString.replace(/[^a-zA-Z0-9 ]/g, "");
        if (removeNumbers) outputString = outputString.replace(/[^a-zA-Z ]/g, "");
        if (removeSpaces) outputString = outputString.replace(/\s/g, "");
        return outputString;
    }
    function getDocUsername(doc) {
        const columnPage = doc.getElementById("columnpage"), submissionIdContainer = null == columnPage ? void 0 : columnPage.querySelector('div[class*="submission-id-container"]'), usernameContainer = null == submissionIdContainer ? void 0 : submissionIdContainer.querySelector('a[href*="user"]');
        if (null != usernameContainer) {
            let username = usernameContainer.href;
            username = username.trimEnd("/");
            username = username.split("/").pop();
            return username;
        }
    }
    var BackwardSearch_awaiter = function(thisArg, _arguments, P, generator) {
        return new (P || (P = Promise))((function(resolve, reject) {
            function fulfilled(value) {
                try {
                    step(generator.next(value));
                } catch (e) {
                    reject(e);
                }
            }
            function rejected(value) {
                try {
                    step(generator.throw(value));
                } catch (e) {
                    reject(e);
                }
            }
            function step(result) {
                result.done ? resolve(result.value) : function adopt(value) {
                    return value instanceof P ? value : new P((function(resolve) {
                        resolve(value);
                    }));
                }(result.value).then(fulfilled, rejected);
            }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        }));
    };
    class BackwardSearch {
        constructor(currSid, amount, currSubmissionPageNo) {
            this.sidToIgnore = [];
            this._currSid = currSid;
            this._amount = amount;
            this.currSubmissionPageNo = currSubmissionPageNo;
            this.sidToIgnore.push(currSid);
        }
        search() {
            return BackwardSearch_awaiter(this, void 0, void 0, (function*() {
                var _a, _b;
                const isInGallery = isSubmissionPageInGallery(document), isInScraps = isSubmissionPageInScraps(document);
                if (!isInGallery && !isInScraps) return {};
                const columnpage = document.getElementById("columnpage"), submissionIdContainer = null == columnpage ? void 0 : columnpage.querySelector('div[class*="submission-id-container"]'), submissionTitle = null == submissionIdContainer ? void 0 : submissionIdContainer.querySelector('div[class*="submission-title"]'), currTitle = null === (_b = null === (_a = null == submissionTitle ? void 0 : submissionTitle.querySelector("h2")) || void 0 === _a ? void 0 : _a.querySelector("p")) || void 0 === _b ? void 0 : _b.textContent;
                if (string.isNullOrWhitespace(currTitle)) return {};
                const currUsername = getDocUsername(document), folderId = getCurrGalleryFolder();
                Logger.logInfo(`${scriptName}: finding submission page...`);
                if (null == this.currSubmissionPageNo || this.currSubmissionPageNo < 1) if (isInGallery) this.currSubmissionPageNo = yield requestHelper.UserRequests.GalleryRequests.Gallery.getSubmissionPageNo(currUsername, this._currSid, folderId, -1, -1); else if (isInScraps) this.currSubmissionPageNo = yield requestHelper.UserRequests.GalleryRequests.Scraps.getSubmissionPageNo(currUsername, this._currSid, -1, -1);
                Logger.logInfo(`${scriptName}: found submission on page '${this.currSubmissionPageNo}'`);
                Logger.logInfo(`${scriptName}: searching figures backward...`);
                let figures = [];
                if (isInGallery) figures = yield requestHelper.UserRequests.GalleryRequests.Gallery.getFiguresInFolderBetweenPages(currUsername, folderId, this.currSubmissionPageNo, this.currSubmissionPageNo + this._amount); else if (isInScraps) figures = yield requestHelper.UserRequests.GalleryRequests.Scraps.getFiguresBetweenPages(currUsername, this.currSubmissionPageNo, this.currSubmissionPageNo + this._amount);
                let figuresFlattend = figures.flat();
                figuresFlattend = figuresFlattend.filter((figure => !this.sidToIgnore.includes(parseInt(figure.id.trimStart("sid-")))));
                figuresFlattend = figuresFlattend.filter((figure => this.figureTitleIsGenerallyEqual(figure, currTitle)));
                figuresFlattend.reverse();
                Logger.logInfo(`${scriptName}: searching figures backward found '${figuresFlattend.length}' figures`);
                Logger.logInfo(`${scriptName}: loading submission pages...`);
                const result = {};
                for (let i = 0; i < figuresFlattend.length; i++) {
                    const figureSid = figuresFlattend[i].id.trimStart("sid-"), subDoc = yield requestHelper.SubmissionRequests.getSubmissionPage(parseInt(figureSid)), img = null == subDoc ? void 0 : subDoc.getElementById("submissionImg");
                    if (null != img) {
                        img.setAttribute("wal-index", (-(figuresFlattend.length - i)).toString());
                        img.setAttribute("wal-sid", figureSid);
                        result[parseInt(figureSid)] = img;
                        Logger.logInfo(`${scriptName}: loaded submission '${figureSid}' with index '${(-(figuresFlattend.length - i)).toString()}'`);
                    }
                }
                return result;
            }));
        }
        figureTitleIsGenerallyEqual(figure, title) {
            const figCaption = figure.querySelector("figcaption"), titleElem = null == figCaption ? void 0 : figCaption.querySelector('a[href*="view"]');
            if (null != titleElem) {
                const figTitleGeneralized = generalizeString(titleElem.title.toLowerCase(), true, true, true, true, true, true), currTitleGeneralized = generalizeString(title, true, true, true, true, true, true);
                return figTitleGeneralized.includes(currTitleGeneralized) || currTitleGeneralized.includes(figTitleGeneralized);
            }
            return false;
        }
    }
    var ForwardSearch_awaiter = function(thisArg, _arguments, P, generator) {
        return new (P || (P = Promise))((function(resolve, reject) {
            function fulfilled(value) {
                try {
                    step(generator.next(value));
                } catch (e) {
                    reject(e);
                }
            }
            function rejected(value) {
                try {
                    step(generator.throw(value));
                } catch (e) {
                    reject(e);
                }
            }
            function step(result) {
                result.done ? resolve(result.value) : function adopt(value) {
                    return value instanceof P ? value : new P((function(resolve) {
                        resolve(value);
                    }));
                }(result.value).then(fulfilled, rejected);
            }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        }));
    };
    class ForwardSearch {
        constructor(currSid, currSubmissionPageNo) {
            this.sidToIgnore = [];
            this._currSid = currSid;
            this.currSubmissionPageNo = currSubmissionPageNo;
            this.sidToIgnore.push(currSid);
        }
        search() {
            return ForwardSearch_awaiter(this, void 0, void 0, (function*() {
                var _a, _b;
                const isInGallery = isSubmissionPageInGallery(document), isInScraps = isSubmissionPageInScraps(document);
                if (!isInGallery && !isInScraps) return {};
                const columnpage = document.getElementById("columnpage"), submissionIdContainer = null == columnpage ? void 0 : columnpage.querySelector('div[class*="submission-id-container"]'), submissionTitle = null == submissionIdContainer ? void 0 : submissionIdContainer.querySelector('div[class*="submission-title"]'), currTitle = null === (_b = null === (_a = null == submissionTitle ? void 0 : submissionTitle.querySelector("h2")) || void 0 === _a ? void 0 : _a.querySelector("p")) || void 0 === _b ? void 0 : _b.textContent;
                if (string.isNullOrWhitespace(currTitle)) return {};
                const currUsername = getDocUsername(document), folderId = getCurrGalleryFolder();
                Logger.logInfo(`${scriptName}: finding submission page...`);
                if (null == this.currSubmissionPageNo || this.currSubmissionPageNo < 1) if (isInGallery) this.currSubmissionPageNo = yield requestHelper.UserRequests.GalleryRequests.Gallery.getSubmissionPageNo(currUsername, this._currSid, folderId, -1, -1); else if (isInScraps) this.currSubmissionPageNo = yield requestHelper.UserRequests.GalleryRequests.Scraps.getSubmissionPageNo(currUsername, this._currSid, -1, -1);
                Logger.logInfo(`${scriptName}: found submission on page '${this.currSubmissionPageNo}'`);
                Logger.logInfo(`${scriptName}: searching figures forward...`);
                let figures = [];
                if (isInGallery) figures = yield requestHelper.UserRequests.GalleryRequests.Gallery.getFiguresInFolderBetweenIds(currUsername, folderId, void 0, this._currSid); else if (isInScraps) figures = yield requestHelper.UserRequests.GalleryRequests.Scraps.getFiguresBetweenIds(currUsername, void 0, this._currSid);
                let figuresFlattend = figures.flat();
                figuresFlattend = figuresFlattend.filter((figure => !this.sidToIgnore.includes(parseInt(figure.id.trimStart("sid-")))));
                figuresFlattend = figuresFlattend.filter((figure => this.figureTitleIsGenerallyEqual(figure, currTitle)));
                figuresFlattend.reverse();
                Logger.logInfo(`${scriptName}: searching figures forward found '${figuresFlattend.length}' figures`);
                Logger.logInfo(`${scriptName}: loading submission pages...`);
                const result = {};
                for (let i = 0; i < figuresFlattend.length; i++) {
                    const figureSid = figuresFlattend[i].id.trimStart("sid-"), subDoc = yield requestHelper.SubmissionRequests.getSubmissionPage(parseInt(figureSid)), img = null == subDoc ? void 0 : subDoc.getElementById("submissionImg");
                    if (null != img) {
                        img.setAttribute("wal-index", (i + 1).toString());
                        img.setAttribute("wal-sid", figureSid);
                        result[parseInt(figureSid)] = img;
                        Logger.logInfo(`${scriptName}: loaded submission '${figureSid}' with index '${(i + 1).toString()}'`);
                    }
                }
                return result;
            }));
        }
        figureTitleIsGenerallyEqual(figure, title) {
            const figCaption = figure.querySelector("figcaption"), titleElem = null == figCaption ? void 0 : figCaption.querySelector('a[href*="view"]');
            if (null != titleElem) {
                const figTitleGeneralized = generalizeString(titleElem.title.toLowerCase(), true, true, true, true, true, true), currTitleGeneralized = generalizeString(title, true, true, true, true, true, true);
                return figTitleGeneralized.includes(currTitleGeneralized) || currTitleGeneralized.includes(figTitleGeneralized);
            }
            return false;
        }
    }
    class Lightbox {
        constructor(orgSid, imgs) {
            this.currWalIndex = 0;
            this._imgCount = -1;
            this._lightboxContainer = document.body.querySelector('div[class*="lightbox-submission"]');
            this._lightboxContainer.innerHTML = "";
            this._lightboxContainer = this._lightboxContainer.readdToDom();
            this._lightboxContainer.addEventListener("click", (() => {
                this.isHidden = true;
            }));
            this._imgCount = Object.keys(imgs).length;
            const orgImgClone = document.getElementById("columnpage").querySelector(`img[wal-sid="${orgSid}"]`).readdToDom();
            imgs[orgSid] = orgImgClone;
            const sortedImages = Object.values(imgs).sort(((a, b) => {
                var _a, _b;
                return parseInt(null !== (_a = a.getAttribute("wal-index")) && void 0 !== _a ? _a : "0") - parseInt(null !== (_b = b.getAttribute("wal-index")) && void 0 !== _b ? _b : "0");
            }));
            for (const img of sortedImages) {
                img.addEventListener("click", (() => {
                    var _a;
                    this.currWalIndex = null !== (_a = this.getIndexOfClickedImage(img)) && void 0 !== _a ? _a : 0;
                    this.isHidden = false;
                }));
                const clone = img.cloneNode(false);
                clone.classList.add("hidden");
                this._lightboxContainer.appendChild(clone);
            }
            this._boundHandleArrowKeys = this.handleArrowKeys.bind(this);
        }
        get isHidden() {
            return this._lightboxContainer.classList.contains("hidden");
        }
        set isHidden(value) {
            var _a;
            if (this.isHidden !== value) if (value) {
                window.removeEventListener("keydown", this._boundHandleArrowKeys);
                this._lightboxContainer.classList.add("hidden");
                for (const child of Array.from(this._lightboxContainer.children)) child.classList.add("hidden");
            } else {
                window.addEventListener("keydown", this._boundHandleArrowKeys);
                null === (_a = this._lightboxContainer.children[this.currWalIndex]) || void 0 === _a || _a.classList.remove("hidden");
                this._lightboxContainer.classList.remove("hidden");
            }
        }
        navigateLeft() {
            if (this.currWalIndex > 0) {
                const currImg = this._lightboxContainer.children[this.currWalIndex], prevImg = this._lightboxContainer.children[this.currWalIndex - 1];
                if (null != currImg && null != prevImg) {
                    currImg.classList.add("hidden");
                    prevImg.classList.remove("hidden");
                }
                this.currWalIndex--;
            }
        }
        navigateRight() {
            if (this.currWalIndex < this._imgCount) {
                const currImg = this._lightboxContainer.children[this.currWalIndex], nextImg = this._lightboxContainer.children[this.currWalIndex + 1];
                if (null != currImg && null != nextImg) {
                    currImg.classList.add("hidden");
                    nextImg.classList.remove("hidden");
                }
                this.currWalIndex++;
            }
        }
        handleArrowKeys(event) {
            switch (event.key) {
              case "ArrowLeft":
              case "ArrowUp":
                this.navigateLeft();
                break;

              case "ArrowRight":
              case "ArrowDown":
                this.navigateRight();
            }
            event.preventDefault();
        }
        getIndexOfClickedImage(img) {
            let clickedWalIndex = img.getAttribute("wal-index");
            if (!string.isNullOrWhitespace(clickedWalIndex)) {
                this.currWalIndex = parseInt(clickedWalIndex);
                const clickedImg = this._lightboxContainer.querySelector(`img[wal-index="${this.currWalIndex}"]`);
                return null == clickedImg ? void 0 : clickedImg.getIndexOfThis();
            }
        }
    }
    var AutoLoader_awaiter = function(thisArg, _arguments, P, generator) {
        return new (P || (P = Promise))((function(resolve, reject) {
            function fulfilled(value) {
                try {
                    step(generator.next(value));
                } catch (e) {
                    reject(e);
                }
            }
            function rejected(value) {
                try {
                    step(generator.throw(value));
                } catch (e) {
                    reject(e);
                }
            }
            function step(result) {
                result.done ? resolve(result.value) : function adopt(value) {
                    return value instanceof P ? value : new P((function(resolve) {
                        resolve(value);
                    }));
                }(result.value).then(fulfilled, rejected);
            }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        }));
    };
    class AutoLoader {
        constructor() {
            var _a;
            this.currComicNav = null;
            this.comicNavExists = false;
            this.currSid = -1;
            const descriptionElem = null === (_a = document.getElementById("columnpage")) || void 0 === _a ? void 0 : _a.querySelector('div[class*="submission-description"]');
            if (null != descriptionElem) {
                this.currComicNav = ComicNavigation.fromElement(descriptionElem);
                if (null != this.currComicNav) if (-1 !== this.currComicNav.prevId || -1 !== this.currComicNav.firstId || -1 !== this.currComicNav.nextId) {
                    this.comicNavExists = true;
                    if (overwriteNavButtonsSetting.value) this.overwriteNavButtons();
                }
            }
            this.currSid = getDocViewSid(document);
            this.submissionImg = document.getElementById("submissionImg");
            this.submissionImg.setAttribute("wal-index", "0");
            this.submissionImg.setAttribute("wal-sid", this.currSid.toString());
            const searchButton = document.createElement("a");
            searchButton.id = this.comicNavExists ? "wal-auto-load-button" : "wal-search-button";
            searchButton.classList.add("wal-button", "button", "standard", "mobile-fix");
            searchButton.type = "button";
            searchButton.style.margin = "20px 0 10px 0";
            searchButton.textContent = this.comicNavExists ? "Auto load Pages" : "Search for similar Pages";
            searchButton.addEventListener("click", (() => {
                if (this.comicNavExists) this.startAutoloader(); else this.startSimilarSearch();
                searchButton.remove();
            }));
            this.submissionImg.parentNode.appendChild(document.createElement("br"));
            this.submissionImg.parentNode.appendChild(searchButton);
            const loadingSpinnerContainer = document.createElement("div");
            loadingSpinnerContainer.classList.add("wal-loading-spinner");
            loadingSpinnerContainer.style.margin = "20px 0 20px 0";
            this._loadingSpinner = new window.FALoadingSpinner(loadingSpinnerContainer);
            this._loadingSpinner.delay = loadingSpinSpeedSetting.value;
            this._loadingSpinner.spinnerThickness = 6;
            this.submissionImg.parentNode.appendChild(loadingSpinnerContainer);
        }
        startAutoloader() {
            this.startAutoLoaderAsync();
        }
        startAutoLoaderAsync() {
            return AutoLoader_awaiter(this, void 0, void 0, (function*() {
                this._loadingSpinner.visible = true;
                const autoLoader = new AutoLoaderSearch(this.submissionImg, this.currSid, this.currComicNav), submissions = yield autoLoader.search();
                this.addLoadedSubmissions(submissions);
                if (useCustomLightboxSetting.value) new Lightbox(this.currSid, submissions);
                this._loadingSpinner.visible = false;
            }));
        }
        startSimilarSearch() {
            this.startSimilarSearchAsync();
        }
        startSimilarSearchAsync() {
            return AutoLoader_awaiter(this, void 0, void 0, (function*() {
                this._loadingSpinner.visible = true;
                const forwardSearch = new ForwardSearch(this.currSid), submissionsAfter = yield forwardSearch.search(), backwardSearch = new BackwardSearch(this.currSid, backwardSearchSetting.value, forwardSearch.currSubmissionPageNo);
                backwardSearch.sidToIgnore.push(...Object.keys(submissionsAfter).map(Number));
                const submissionsBefore = yield backwardSearch.search();
                this.addLoadedSubmissions(submissionsBefore, submissionsAfter);
                if (useCustomLightboxSetting.value) new Lightbox(this.currSid, Object.assign(Object.assign({}, submissionsBefore), submissionsAfter));
                this._loadingSpinner.visible = false;
            }));
        }
        addLoadedSubmissions(...imgsArr) {
            const columnpage = document.getElementById("columnpage");
            for (const imgs of imgsArr) {
                Logger.logInfo(`${scriptName}: adding '${Object.keys(imgs).length}' submissions...`);
                let prevSid = this.currSid;
                for (const sid of Object.keys(imgs).map(Number)) {
                    if (imgs[sid].getAttribute("wal-sid") === this.currSid.toString()) continue;
                    const lastImg = columnpage.querySelector(`img[wal-sid="${prevSid}"]`), lastIndex = parseInt(lastImg.getAttribute("wal-index"));
                    if (parseInt(imgs[sid].getAttribute("wal-index")) < lastIndex) {
                        lastImg.insertBeforeThis(imgs[sid]);
                        imgs[sid].insertAfterThis(document.createElement("br"));
                        imgs[sid].insertAfterThis(document.createElement("br"));
                        checkTags(imgs[sid]);
                        Logger.logInfo(`${scriptName}: added submission ${sid} before submission ${prevSid}`);
                    } else {
                        lastImg.insertAfterThis(imgs[sid]);
                        imgs[sid].insertBeforeThis(document.createElement("br"));
                        imgs[sid].insertBeforeThis(document.createElement("br"));
                        checkTags(imgs[sid]);
                        Logger.logInfo(`${scriptName}: added submission ${sid} after submission ${prevSid}`);
                    }
                    prevSid = sid;
                }
            }
        }
        overwriteNavButtons() {
            var _a, _b, _c, _d, _e, _f;
            if (!this.comicNavExists) return;
            const columnpage = document.getElementById("columnpage"), favoriteNav = null == columnpage ? void 0 : columnpage.querySelector('div[class*="favorite-nav"]');
            let prevButton = null == favoriteNav ? void 0 : favoriteNav.children[0];
            if (null != prevButton && -1 !== this.currComicNav.prevId) if (null !== (_c = null === (_b = null === (_a = prevButton.textContent) || void 0 === _a ? void 0 : _a.toLowerCase()) || void 0 === _b ? void 0 : _b.includes("prev")) && void 0 !== _c ? _c : false) prevButton.href = `/view/${this.currComicNav.prevId}/`; else {
                const prevButtonReal = document.createElement("a");
                prevButtonReal.href = `/view/${this.currComicNav.prevId}/`;
                prevButtonReal.classList.add("button", "standard", "mobile-fix");
                prevButtonReal.textContent = "Prev";
                prevButtonReal.style.marginRight = "4px";
                prevButton.insertBeforeThis(prevButtonReal);
            }
            let nextButton = null == favoriteNav ? void 0 : favoriteNav.children[favoriteNav.children.length - 1];
            if (null != nextButton && -1 !== this.currComicNav.nextId) if (null !== (_f = null === (_e = null === (_d = nextButton.textContent) || void 0 === _d ? void 0 : _d.toLowerCase()) || void 0 === _e ? void 0 : _e.includes("next")) && void 0 !== _f ? _f : false) nextButton.href = `/view/${this.currComicNav.nextId}/`; else {
                const nextButtonReal = document.createElement("a");
                nextButtonReal.href = `/view/${this.currComicNav.nextId}/`;
                nextButtonReal.classList.add("button", "standard", "mobile-fix");
                nextButtonReal.textContent = "Next";
                nextButtonReal.style.marginLeft = "4px";
                nextButton.insertAfterThis(nextButtonReal);
            }
        }
    }
    const scriptName = "FA Webcomic Auto Loader", customSettings = new window.FACustomSettings("Midori's Script Settings", `${scriptName} Settings`), showSearchButtonSetting = customSettings.newSetting(window.FASettingType.Boolean, "Similar Search Button");
    showSearchButtonSetting.description = "Sets wether the search for similar Pages button is show.";
    showSearchButtonSetting.defaultValue = true;
    const loadingSpinSpeedSetting = customSettings.newSetting(window.FASettingType.Number, "Loading Animation");
    loadingSpinSpeedSetting.description = "Sets the duration that the loading animation takes for a full rotation in milliseconds.";
    loadingSpinSpeedSetting.defaultValue = 1e3;
    const backwardSearchSetting = customSettings.newSetting(window.FASettingType.Number, "Backward Search Amount");
    backwardSearchSetting.description = "Sets the amount of similar pages to search backward. (More Pages take longer)";
    backwardSearchSetting.defaultValue = 3;
    const overwriteNavButtonsSetting = customSettings.newSetting(window.FASettingType.Boolean, "Overwrite Nav Buttons");
    overwriteNavButtonsSetting.description = "Sets wether the default Navigation Buttons (next/prev) are overwritten by the Auto-Loader. (Works only if comic navigation is present)";
    overwriteNavButtonsSetting.defaultValue = true;
    const useCustomLightboxSetting = customSettings.newSetting(window.FASettingType.Boolean, "Use Custom Lightbox");
    useCustomLightboxSetting.description = "Sets wether the default Lightbox (fullscreen view) is overwritten by the Auto-Loader.";
    useCustomLightboxSetting.defaultValue = true;
    customSettings.loadSettings();
    const requestHelper = new window.FARequestHelper(2);
    if (customSettings.isFeatureEnabled) {
        const matchList = new window.FAMatchList(customSettings);
        matchList.matches = [ "net/view" ];
        matchList.runInIFrame = false;
        if (matchList.hasMatch) new AutoLoader;
    }
})();