U9A9.com-首页预览图

从U9A9.com的首页加载预览图片

// ==UserScript==
// @name         U9A9.com-首页预览图
// @namespace    none
// @description  从U9A9.com的首页加载预览图片
// @version      2.2.2
// @license      MIT
// @homepage     https://sleazyfork.org/zh-CN/scripts/511302-u9a9-com-%E9%A6%96%E9%A1%B5%E9%A2%84%E8%A7%88%E5%9B%BE?locale_override=1
// @supportURL   https://sleazyfork.org/zh-CN/scripts/511302-u9a9-com-%E9%A6%96%E9%A1%B5%E9%A2%84%E8%A7%88%E5%9B%BE?locale_override=1
// @match        https://u9a9.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=u9a9.com
// @run-at       document-end
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @connect      *
// ==/UserScript==

(function() {
    'use strict';

    const processedLinks = new Set();
    const imageCache = new Map();
    let requestQueue = Promise.resolve();
    const requestDelay = 100;
    const initialLoadCount = 20;
    const batchSize = 20;

    function addImage(url, linkElement) {
        if (processedLinks.has(url)) return;
        processedLinks.add(url);

        if (imageCache.has(url)) {
            addImageIcon(imageCache.get(url), linkElement);
        } else {
            requestQueue = requestQueue.then(() => processImageLink(url, linkElement))
                .then(() => new Promise(resolve => setTimeout(resolve, requestDelay)));
        }
    }

    async function processImageLink(url, linkElement) {
        try {
            const html = await fetchPage(url);
            const imageUrl = extractFirstImageUrl(html);
            if (imageUrl) {
                imageCache.set(url, imageUrl);
                addImageIcon(imageUrl, linkElement);
            } else {
                const existingIcon = linkElement.previousElementSibling;
                if (existingIcon && existingIcon.classList.contains('lmt-icon')) {
                    existingIcon.remove();
                }
            }
        } catch (error) {
            console.error('Error processing image link:', error);
        }
    }

    function fetchPage(url) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: url,
                onload: response => resolve(response.responseText),
                onerror: error => reject(error)
            });
        });
    }

    function extractFirstImageUrl(html) {
        const patterns = [
            /https?:\/\/.*\.u99\.pics\/[^"']+\.(?:jpg|jpeg|png|gif)/i,
            /\/\/.*\.u99\.pics\/[^"']+\.(?:jpg|jpeg|png|gif)/i
        ];

        for (let pattern of patterns) {
            const match = html.match(pattern);
            if (match) {
                let url = match[0].split('"')[0].split("'")[0];
                return url.startsWith('//') ? 'https:' + url : url;
            }
        }

        return null;
    }

    function addImageIcon(imageUrl, linkElement) {
        let span = linkElement.previousElementSibling;
        if (!span || !span.classList.contains('lmt-icon')) {
            span = document.createElement("span");
            span.classList.add('lmt-icon');
            span.innerHTML = '🖼️';
            span.style.cursor = 'pointer';
            linkElement.parentNode.insertBefore(span, linkElement);
        }

        imageUrl = imageUrl.split('"')[0].split("'")[0];
        span.dataset.lmt = imageUrl;

        [span, linkElement].forEach(el => {
            el.addEventListener('mousemove', (e) => showImage(imageUrl, e));
            el.addEventListener('mouseleave', hideImage);
        });
    }

    function showImage(imageUrl, event) {
        let container = document.getElementById('LMT_Frame');
        if (!container) {
            container = document.createElement('div');
            container.id = 'LMT_Frame';
            container.style.position = 'fixed';
            container.style.zIndex = '10000';
            container.style.display = 'none';
            document.body.appendChild(container);
        }

        const img = document.createElement('img');
        img.src = imageUrl;
        img.style.width = '100%';
        img.style.height = 'auto';
        img.style.border = '2px solid #333';
        img.style.borderRadius = '5px';
        img.style.boxShadow = '0 0 10px rgba(0,0,0,0.5)';

        container.innerHTML = '';
        container.appendChild(img);
        container.style.display = 'block';

        // 计算位置
        const maxWidth = 540;
        const maxHeight = 540;
        container.style.maxWidth = `${maxWidth}px`;
        container.style.maxHeight = `${maxHeight}px`;

        let left = event.clientX + 10;
        let top = event.clientY + 10;

        // 确保图片不会超出屏幕右侧
        if (left + maxWidth > window.innerWidth) {
            left = window.innerWidth - maxWidth - 10;
        }

        // 确保图片不会超出屏幕底部
        if (top + maxHeight > window.innerHeight) {
            top = window.innerHeight - maxHeight - 10;
        }

        container.style.left = `${left}px`;
        container.style.top = `${top}px`;
    }

    function hideImage() {
        const container = document.getElementById('LMT_Frame');
        if (container) {
            container.style.display = 'none';
        }
    }

    function loadBatch(links, startIndex) {
        const endIndex = Math.min(startIndex + batchSize, links.length);
        for (let i = startIndex; i < endIndex; i++) {
            const link = links[i];
            const fullUrl = 'https://u9a9.com' + link.getAttribute('href');
            addImage(fullUrl, link);
        }
        return endIndex;
    }

    function initLazyLoading(links) {
        let currentIndex = 0;

        // 初始加载
        currentIndex = loadBatch(links, currentIndex);

        // 监听滚动事件
        window.addEventListener('scroll', () => {
            if (currentIndex >= links.length) return;

            const lastLink = links[currentIndex - 1];
            if (lastLink && isElementInViewport(lastLink)) {
                currentIndex = loadBatch(links, currentIndex);
            }
        });
    }

    function isElementInViewport(el) {
        const rect = el.getBoundingClientRect();
        return (
            rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
            rect.right <= (window.innerWidth || document.documentElement.clientWidth)
        );
    }

    function init() {
        const links = Array.from(document.querySelectorAll('a[href^="/view/"]'));
        initLazyLoading(links);
    }

    window.addEventListener('load', init);
})();