您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Fixes UI visibility issues for TimerHooker Unified Version.
// ==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://greasyfork.org/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);