网页加载分析(改)

测试网页加载速度并显示加载最慢的三个网址的域名,二改添加了对Via浏览器toast的调用,添加高斯模糊效果。

// ==UserScript==
// @name         网页加载分析(改)
// @version      1.14
// @description  测试网页加载速度并显示加载最慢的三个网址的域名,二改添加了对Via浏览器toast的调用,添加高斯模糊效果。
// @description:en Test the webpage loading speed and display the domain names of the three slowest loading URLs.
// @match        *://*/*
// @run-at       document-start
// @author       yzcjd & nobody
// @author2      Lama AI 辅助
// @namespace    https://scriptcat.org/zh-CN/users/157252
// @exclude      *://*.cloudflare.com/*
// @exclude      *://*.recaptcha.net/*
// @license      MIT
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// ==/UserScript==

(function() {
    'use strict';

    const currentDomain = location.hostname || 'unknown';
    // 检查是否在 GM 环境中
    const isGMEnvironment = typeof GM_getValue === 'function' && typeof GM_setValue === 'function' && typeof GM_registerMenuCommand === 'function';

    // 初始化设置
    let isEnabled = true; // 默认启用网页加载测试
    let useBlurDisplay = true; // 默认使用高斯模糊显示
    let domainSettings = {};

    if (isGMEnvironment) {
        domainSettings = GM_getValue('domainSettings', {});
        isEnabled = domainSettings[currentDomain] !== false;
        useBlurDisplay = GM_getValue('useBlurDisplay', false);

        GM_registerMenuCommand(
            `${isEnabled ? '❌禁用' : '✅启用'} 网页加载测试(${currentDomain})`,
            () => {
                domainSettings[currentDomain] = !isEnabled;
                GM_setValue('domainSettings', domainSettings);
                alert(`网页加载测试已${!isEnabled ? '✅启用' : '❌禁用'}(${currentDomain}),刷新页面生效。`);
            }
        );
        GM_registerMenuCommand(
            `${useBlurDisplay ? '❌禁用' : '✅启用'} 高斯模糊显示`,
            () => {
                GM_setValue('useBlurDisplay', !useBlurDisplay);
                alert(`高斯模糊显示已${!isEnabled ? '✅启用' : '❌禁用'},刷新页面生效。`);
            }
        );
        if (!isEnabled) return;
    }

    const loadTimeElement = document.createElement('div');
    loadTimeElement.id = 'loadTimeDisplay';
    loadTimeElement.style.cssText = `
        position: fixed;
        top: 85%;
        left: 50%;
        transform: translate(-50%, -50%);
        background: rgba(255, 255, 255, 0.3); /* 半透明毛玻璃背景 */
        backdrop-filter: blur(16px); /* 高斯模糊 */
        -webkit-backdrop-filter: blur(16px); /* 兼容 Safari */
        padding: 12px 20px; /* 舒适内边距 */
        border-radius: 22px; /* iOS 风格圆角 */
        box-shadow: 0 6px 24px rgba(0, 0, 0, 0.15); /* 柔和阴影 */
        white-space: nowrap;
        width: auto; /* 自适应宽度 */
        max-width: 90%; /* 防止溢出 */
        z-index: 9999;
        color: #1C2526; /* 深色文字,确保可读 */
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; /* iOS 字体 */
        font-size: 15px; /* 优雅字体大小 */
        font-weight: 500; /* 适中字重 */
        text-align: center; /* 文字居中 */
        border: 1px solid rgba(255, 255, 255, 0.25); /* 微弱边框增加质感 */
        opacity: 0; /* 初始透明 */
        transition: opacity 0.3s ease-in-out; /* 淡入动画 */
    `;

    // 兼容不支持 backdrop-filter 的浏览器
    if (!CSS.supports('backdrop-filter', 'blur(16px)')) {
        loadTimeElement.style.background = 'rgba(240, 240, 240, 0.85)';
    }

    const startTime = performance.now();
    const slowestRequests = new Set();
    const maxSlowRequests = 3;

    const networkObserver = new PerformanceObserver((list) => {
        list.getEntries().forEach((entry) => {
            slowestRequests.add({
                name: entry.name,
                duration: entry.duration,
            });
            if (slowestRequests.size > maxSlowRequests) {
                const sorted = Array.from(slowestRequests).sort((a, b) => b.duration - a.duration);
                slowestRequests.clear();
                sorted.slice(0, maxSlowRequests).forEach((req) => slowestRequests.add(req));
            }
        });
    });

    networkObserver.observe({
        entryTypes: ['resource']
    });

    window.addEventListener('load', () => {
        networkObserver.disconnect();
        const endTime = performance.now();
        const timeElapsed = endTime - startTime;
        const sortedRequests = Array.from(slowestRequests).sort((a, b) => b.duration - a.duration);

        const networkInfoHTML = sortedRequests.length ?
            sortedRequests
            .map((req) => {
                try {
                    const url = new URL(req.name);
                    return `slow: ${url.hostname} (${req.duration.toFixed(2)}ms)<br>`;
                } catch {
                    return `slow: Invalid URL (${req.duration.toFixed(2)}ms)<br>`;
                }
            })
            .join('') :
            '[none]';

        const networkInfo = sortedRequests.length ?
            sortedRequests
            .map((req) => {
                try {
                    const url = new URL(req.name);
                    return `Slow: ${url.hostname} (${req.duration.toFixed(2)}ms)`;
                } catch {
                    return `Slow: Invalid URL (${req.duration.toFixed(2)}ms)`;
                }
            })
            .join('\n') :
            '[none]';

        if (window.via && typeof window.via.toast === 'function' && !useBlurDisplay) {
            window.via.toast(`Time: ${timeElapsed.toFixed(2)}ms\n${networkInfo}`);
        } else {
            loadTimeElement.innerHTML = `<h2 style="margin:0;font-size:16px;font-weight:600">Time: ${timeElapsed.toFixed(2)}ms</h2>${networkInfoHTML}`;
            document.body.appendChild(loadTimeElement);
            requestAnimationFrame(() => {
                loadTimeElement.style.opacity = '1';
            });
            setTimeout(() => {
                requestAnimationFrame(() => {
                    loadTimeElement.style.opacity = '0';
                });
                setTimeout(() => loadTimeElement.remove(), 300);
            }, 2600);
        }

        slowestRequests.clear();
    });
})();