您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Speeds up countdown timers with a fully movable UI designed for Android screens.
当前为
// ==UserScript== // @name TimerHooker Android MD3 Version // @version 2.3.0 // @description Speeds up countdown timers with a fully movable UI designed for Android screens. // @include * // @author Govindarajulu // @match http://*/* // @run-at document-start // @grant none // @license GPL-3.0-or-later // @namespace https://greasyfork.org/users/1356925 // ==/UserScript== (function (global) { let isSpeedActive = false; const speedMultiplier = 50; let autoHideTimeout; function overrideTimers(factor) { ["setTimeout", "setInterval"].forEach((method) => { window[method] = ((original) => (fn, time) => original(fn, time / factor))(window[method]); }); } const TimerHooker = { toggleSpeed: function () { isSpeedActive = !isSpeedActive; overrideTimers(isSpeedActive ? speedMultiplier : 1); const btn = document.getElementById("toggleSpeedBtn"); if (btn) btn.textContent = isSpeedActive ? "Stop" : "Speed"; console.log(`[TimerHooker] Countdown timers accelerated: x${isSpeedActive ? speedMultiplier : 1}`); TimerHooker.resetAutoHide(); // Reset hide timer when toggled }, createUI: function () { if (document.getElementById("timerHookerUI")) return; const speedControl = document.createElement("div"); speedControl.id = "timerHookerUI"; speedControl.style = ` position: fixed; top: 50%; left: -35px; z-index: 99999; background: rgba(0,0,0,0.3); color: white; padding: 6px 12px; border-radius: 40px; font-size: 12px; font-weight: 500; text-align: center; cursor: grab; backdrop-filter: blur(8px); box-shadow: 0px 3px 8px rgba(0,0,0,0.2); user-select: none; transition: left 0.3s ease, top 0.1s ease, background 0.3s ease, color 0.3s ease; touch-action: none; `; speedControl.textContent = "Speed"; speedControl.id = "toggleSpeedBtn"; speedControl.addEventListener("click", () => { speedControl.style.left = "10px"; // Bring button fully into view TimerHooker.toggleSpeed(); }); // Enable **touch-based dragging** across Android screens let startX, startY, isDragging = false; speedControl.addEventListener("touchstart", (e) => { isDragging = true; clearTimeout(autoHideTimeout); // Stop auto-hide when dragged const touch = e.touches[0]; startX = touch.clientX - speedControl.getBoundingClientRect().left; startY = touch.clientY - speedControl.getBoundingClientRect().top; speedControl.style.cursor = "grabbing"; }); document.addEventListener("touchmove", (e) => { if (!isDragging) return; const touch = e.touches[0]; speedControl.style.left = `${Math.min(window.innerWidth - speedControl.offsetWidth, Math.max(0, touch.clientX - startX))}px`; speedControl.style.top = `${Math.min(window.innerHeight - speedControl.offsetHeight, Math.max(0, touch.clientY - startY))}px`; }); document.addEventListener("touchend", () => { isDragging = false; speedControl.style.cursor = "grab"; TimerHooker.resetAutoHide(); // Start hiding after movement stops }); document.body.appendChild(speedControl); TimerHooker.resetAutoHide(); console.log("[TimerHooker] UI optimized for Android successfully."); }, resetAutoHide: function () { clearTimeout(autoHideTimeout); autoHideTimeout = setTimeout(() => { const speedControl = document.getElementById("timerHookerUI"); if (!isDragging) speedControl.style.left = "-35px"; // Move button back to sideline }, 3000); }, handleFullscreen: function () { document.addEventListener("fullscreenchange", () => { const speedControl = document.getElementById("timerHookerUI"); if (document.fullscreenElement) { speedControl.style.display = "none"; // Hide in fullscreen mode } else { speedControl.style.display = "block"; // Show when fullscreen exits } }); }, init: function () { console.log("[TimerHooker] Android MD3 version activated"); this.createUI(); this.handleFullscreen(); } }; if (document.readyState === "complete") { TimerHooker.init(); } else { window.addEventListener("load", () => TimerHooker.init()); } })(window);