Ukrainian flag(ctrl+shift+U)

左下角飄揚勳章。Ctrl+Shift+U 循環切換開啟/關閉。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Ukrainian flag(ctrl+shift+U)
// @namespace    tampermonkey.net
// @version      12.0
// @description  左下角飄揚勳章。Ctrl+Shift+U 循環切換開啟/關閉。
// @author       邢智轩(from China)
// @match        *://*/*
// @run-at       document-start
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    let isTerminated = false; // 用於追蹤使用者是否手動關閉

    // 1. 核心注入函數
    function injectBadge() {
        if (document.getElementById('ua-waving-badge-root')) return;

        const host = document.createElement('div');
        host.id = 'ua-waving-badge-root';
        host.style.cssText = `
            position: fixed !important;
            bottom: 30px !important;
            left: 30px !important;
            z-index: 2147483647 !important;
            pointer-events: none !important;
            display: block !important;
            transition: opacity 0.4s ease, transform 0.4s ease !important;
            opacity: 0;
            transform: translateY(20px);
        `;
        document.documentElement.appendChild(host);

        const shadow = host.attachShadow({mode: 'closed'});

        // SVG 資源
        const tridentSvg = `<svg viewBox="0 0 200 300"><path d="M100 0 L85 45 L40 45 Q20 45 20 80 L20 180 Q20 220 50 220 L65 220 L65 190 L50 190 Q40 190 40 175 L40 90 L75 90 L80 180 Q82 250 100 250 Q118 250 120 180 L125 90 L160 90 L160 175 Q160 190 150 190 L135 190 L135 220 L150 220 Q180 220 180 180 L180 80 Q180 45 160 45 L115 45 Z M100 260 L90 300 L110 300 Z" fill="#FFD700"/></svg>`;
        const shieldSvg = `<svg viewBox="0 0 100 120"><path d="M10 10 Q50 0 90 10 L90 60 Q90 95 50 115 Q10 95 10 60 Z" fill="#0057B7" stroke="#FFD700" stroke-width="4"/><path d="M50 25 V85 M35 35 Q35 75 50 75 Q65 75 65 35 M42 35 V60 M58 35 V60" fill="none" stroke="#FFD700" stroke-width="8" stroke-linecap="round"/></svg>`;

        shadow.innerHTML = `
        <style>
            .flag-container {
                position: relative;
                width: 120px;
                height: 70px;
                background: linear-gradient(to bottom, #0057B7 50%, #FFD700 50%);
                border-radius: 4px;
                overflow: hidden;
                box-shadow: 0 10px 25px rgba(0,0,0,0.5);
                animation: wave 3s infinite ease-in-out;
                transform-origin: left center;
                display: flex;
                align-items: center;
                justify-content: space-around;
                padding: 0 10px;
            }
            .icon { width: 35px; height: auto; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.6)); z-index: 2; }
            @keyframes wave {
                0%, 100% { transform: skewY(0deg) scale(1); }
                25% { transform: skewY(2.5deg) scale(1.02); }
                50% { transform: skewY(-2.5deg) scale(1); }
                75% { transform: skewY(1.5deg) scale(0.98); }
            }
            .flag-container::after {
                content: "";
                position: absolute;
                top: 0; left: -100%;
                width: 100%; height: 100%;
                background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
                animation: shine 4s infinite linear;
            }
            @keyframes shine { 0% { left: -100%; } 20% { left: 100%; } 100% { left: 100%; } }
        </style>
        <div class="flag-container">
            <div class="icon">${tridentSvg}</div>
            <div class="icon">${shieldSvg}</div>
        </div>`;

        // 入場動畫
        requestAnimationFrame(() => {
            host.style.opacity = '1';
            host.style.transform = 'translateY(0)';
        });
    }

    // 2. 快捷鍵切換邏輯 (Ctrl + Shift + U)
    window.addEventListener('keydown', function(e) {
        if (e.ctrlKey && e.shiftKey && e.code === 'KeyU') {
            const root = document.getElementById('ua-waving-badge-root');
            if (root) {
                // 執行關閉
                root.style.opacity = '0';
                root.style.transform = 'translateY(20px)';
                setTimeout(() => {
                    root.remove();
                    isTerminated = true;
                }, 400);
            } else {
                // 執行開啟
                isTerminated = false;
                injectBadge();
            }
        }
    }, true);

    // 3. 強制置頂與自癒校驗 (每 1.5 秒一次)
    function enforce() {
        if (isTerminated) return;

        const root = document.getElementById('ua-waving-badge-root');
        if (!root || !document.documentElement.contains(root)) {
            injectBadge();
        } else {
            // 層級檢查
            if (root.parentElement !== document.documentElement) {
                document.documentElement.appendChild(root);
            }
            if (root.style.zIndex !== '2147483647') {
                root.style.setProperty('z-index', '2147483647', 'important');
            }
        }
    }

    // 初始啟動
    injectBadge();
    setInterval(enforce, 1500);
    const observer = new MutationObserver(enforce);
    observer.observe(document.documentElement, { childList: true, subtree: true });

})();