TimerHooker Unified Version (UI Fix)

Fixes UI visibility issues for TimerHooker Unified Version.

Устаревшая версия за 08.04.2025. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name            TimerHooker Unified Version (UI Fix)
// @version         4.1.0
// @description     Fixes UI visibility issues for TimerHooker Unified Version.
// @author          Combined
// @match           http://*/*
// @run-at          document-start
// @grant           none
// @license         GPL-3.0-or-later
// @namespace https://greatest.deepsurf.us/users/1356925
// ==/UserScript==

(function (global) {
    let isRunning = false; // Tracks whether the timer is active
    let speedMultiplier = localStorage.getItem("timerHookerSpeed") || 2.0; // Default speed (2x)
    let autoHideTimeout; // For auto-hide functionality

    // Override timers with speed adjustment
    const overrideTimers = function (factor) {
        ["setTimeout", "setInterval"].forEach((method) => {
            window[method] = ((original) => (fn, time) => {
                // Exclude video-related timers
                const fnString = fn.toString();
                if (fnString.includes("playback") || fnString.includes("video")) {
                    return original(fn, time);
                }
                return original(fn, time / factor);
            })(window[method]);
        });
    };

    const changeTimerSpeed = function (multiplier) {
        speedMultiplier = multiplier;
        localStorage.setItem("timerHookerSpeed", multiplier);
        if (isRunning) overrideTimers(speedMultiplier);
        console.log(`[TimerHooker] Timer speed changed to x${multiplier}`);
    };

    const createUI = function () {
        const style = `
            .timer-ball {
                position: fixed;
                bottom: 20px;
                right: 20px;
                width: 60px;
                height: 60px;
                border-radius: 50%;
                background-color: #4CAF50;
                display: flex;
                justify-content: center;
                align-items: center;
                box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
                cursor: pointer;
                touch-action: manipulation;
                transition: background-color 0.3s ease;
                z-index: 9999; /* Ensure visibility above other elements */
            }
            .timer-ball:hover {
                background-color: #45A049;
            }
            .timer-symbol {
                font-size: 24px;
                color: white;
                font-weight: bold;
            }
            .slider-container {
                position: fixed;
                bottom: 90px;
                right: 20px;
                z-index: 9999; /* Ensure visibility above other elements */
                display: none;
                background: rgba(0, 0, 0, 0.6);
                padding: 10px;
                border-radius: 10px;
                box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.4);
                user-select: none;
            }
            .slider {
                width: 120px;
            }
        `;

        const styleNode = document.createElement('style');
        styleNode.type = 'text/css';
        styleNode.textContent = style;

        // Main ball UI
        const ball = document.createElement('div');
        ball.className = 'timer-ball';
        ball.innerHTML = '<div class="timer-symbol">▶</div>'; // Start symbol

        // Speed adjustment slider
        const sliderContainer = document.createElement('div');
        sliderContainer.className = 'slider-container';

        const slider = document.createElement('input');
        slider.className = 'slider';
        slider.type = 'range';
        slider.min = "1";
        slider.max = "200";
        slider.value = speedMultiplier * 100; // Scale multiplier to slider range
        slider.addEventListener('input', (event) => {
            const newSpeed = event.target.value / 100;
            changeTimerSpeed(newSpeed);
        });

        sliderContainer.appendChild(slider);

        ball.addEventListener('click', () => {
            isRunning = !isRunning;
            ball.querySelector('.timer-symbol').innerHTML = isRunning ? '■' : '▶'; // Toggle Start/Stop symbol
            overrideTimers(isRunning ? speedMultiplier : 1.0);
            sliderContainer.style.display = isRunning ? 'block' : 'none'; // Show/hide slider
            resetAutoHide(); // Reset auto-hide timer
        });

        // Add auto-hide functionality
        const resetAutoHide = function () {
            clearTimeout(autoHideTimeout);
            autoHideTimeout = setTimeout(() => {
                if (isRunning) sliderContainer.style.display = 'none';
            }, 3000);
        };

        document.body.appendChild(ball);
        document.body.appendChild(sliderContainer);
        document.head.appendChild(styleNode);
    };

    const init = function () {
        console.log("[TimerHooker] Unified version activated.");
        createUI();
        overrideTimers(speedMultiplier);
    };

    // Initialize when the DOM is loaded
    if (document.readyState === "complete") {
        init();
    } else {
        window.addEventListener("load", () => init());
    }
})(window);