Manga Scroll Viewer

Позволяет просматривать мангу в режиме "рулона" на сайтах hentaichan с динамической настройкой ширины и отступов

// ==UserScript==
// @name         Manga Scroll Viewer
// @namespace    http://tampermonkey.net/
// @version      0.6
// @description  Позволяет просматривать мангу в режиме "рулона" на сайтах hentaichan с динамической настройкой ширины и отступов
// @author       You
// @match        https://y.hentaichan.live/online/*.html*
// @match        https://x3.h-chan.me/online/*.html*
// @match        https://xxl.hentaichan.live/online/*.html*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Функция для извлечения массива ссылок на изображения
    function getImageUrls() {
        try {
            if (window.data && window.data.fullimg) {
                return window.data.fullimg || [];
            }
        } catch (e) {
            console.error('Ошибка при доступе к данным:', e);
        }
        return [];
    }

    // Функция для создания плавающего меню с настройками и кнопкой
    function createFloatingMenu(scrollContainerRef) {
        const menu = document.createElement('div');
        menu.style.position = 'fixed';
        menu.style.bottom = '20px';
        menu.style.right = '20px';
        menu.style.zIndex = '1000';
        menu.style.backgroundColor = '#f9f9f9';
        menu.style.padding = '10px';
        menu.style.border = '1px solid #ccc';
        menu.style.borderRadius = '5px';

        const widthLabel = document.createElement('label');
        widthLabel.textContent = 'Ширина контейнера (%): ';
        widthLabel.style.display = 'block';
        widthLabel.style.marginBottom = '5px';
        const widthInput = document.createElement('input');
        widthInput.type = 'range';
        widthInput.value = 50;
        widthInput.min = 10;
        widthInput.max = 100;
        widthInput.style.width = '100%';
        widthLabel.appendChild(widthInput);

        const marginLabel = document.createElement('label');
        marginLabel.textContent = 'Отступ между изображениями (px): ';
        marginLabel.style.display = 'block';
        marginLabel.style.marginBottom = '10px';
        const marginInput = document.createElement('input');
        marginInput.type = 'range';
        marginInput.value = 10;
        marginInput.min = 0;
        marginInput.max = 50;
        marginInput.style.width = '100%';
        marginLabel.appendChild(marginInput);

        const button = document.createElement('button');
        button.textContent = 'Изменить режим чтения';
        button.style.padding = '8px';
        button.style.backgroundColor = '#4CAF50';
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.borderRadius = '5px';
        button.style.cursor = 'pointer';
        button.style.width = '100%';

        menu.appendChild(widthLabel);
        menu.appendChild(marginLabel);
        menu.appendChild(button);

        document.body.appendChild(menu);

        // Динамическое обновление ширины контейнера
        widthInput.addEventListener('input', () => {
            if (scrollContainerRef.container) {
                scrollContainerRef.container.style.width = `${widthInput.value}%`;
            }
        });

        // Динамическое обновление отступов между изображениями
        marginInput.addEventListener('input', () => {
            if (scrollContainerRef.container) {
                const images = scrollContainerRef.container.querySelectorAll('img');
                images.forEach(img => {
                    img.style.marginBottom = `${marginInput.value}px`;
                });
            }
        });

        return { button, widthInput, marginInput };
    }

    // Функция для загрузки всех страниц
    function loadAllPages(button, widthInput, marginInput, scrollContainerRef) {
        const imageUrls = getImageUrls();
        if (imageUrls.length === 0) {
            alert('Не удалось найти ссылки на изображения. Убедитесь, что страница полностью загружена, и JavaScript включен.');
            return;
        }

        // Очистить текущий контейнер с изображением
        const imageContainer = document.getElementById('image');
        if (imageContainer) {
            imageContainer.innerHTML = '';
        }

        // Удалить предыдущий контейнер, если он существует
        if (scrollContainerRef.container) {
            scrollContainerRef.container.remove();
        }

        // Создать новый контейнер для всех изображений
        const scrollContainer = document.createElement('div');
        scrollContainer.style.width = `${widthInput.value}%`;
        scrollContainer.style.margin = '0 auto';
        scrollContainer.style.padding = '10px';
        document.body.appendChild(scrollContainer);
        scrollContainerRef.container = scrollContainer;

        // Изменить состояние кнопки
        button.textContent = `Загружается 0 из ${imageUrls.length} страниц...`;
        button.style.backgroundColor = '#f44336';
        button.disabled = true;

        let loadedImages = 0;

        // Функция для добавления изображения с задержкой
        function addImage(index) {
            if (index >= imageUrls.length) {
                button.textContent = 'Загрузить заново';
                button.style.backgroundColor = '#4CAF50';
                button.disabled = false;
                return;
            }

            const img = document.createElement('img');
            img.src = imageUrls[index];
            img.style.width = '100%';
            img.style.marginBottom = `${marginInput.value}px`;
            img.style.display = 'block';
            img.onload = () => {
                loadedImages++;
                button.textContent = `Загружается ${loadedImages} из ${imageUrls.length} страниц...`;
            };
            img.onerror = () => {
                loadedImages++;
                button.textContent = `Загружается ${loadedImages} из ${imageUrls.length} страниц...`;
                console.warn(`Ошибка загрузки изображения: ${imageUrls[index]}`);
            };
            scrollContainer.appendChild(img);

            setTimeout(() => addImage(index + 1), 500); // Задержка 500 мс
        }

        addImage(0);
    }

    // Инициализация
    const scrollContainerRef = { container: null };
    const { button, widthInput, marginInput } = createFloatingMenu(scrollContainerRef);
    button.addEventListener('click', () => loadAllPages(button, widthInput, marginInput, scrollContainerRef));
})();