TimerHooker Unified Version (UI Fix)

Fixes UI visibility issues for TimerHooker Unified Version.

  1. // ==UserScript==
  2. // @name TimerHooker Unified Version (UI Fix)
  3. // @version 4.1.0
  4. // @description Fixes UI visibility issues for TimerHooker Unified Version.
  5. // @author Combined
  6. // @match http://*/*
  7. // @run-at document-start
  8. // @grant none
  9. // @license GPL-3.0-or-later
  10. // @namespace https://gf.qytechs.cn/users/1356925
  11. // ==/UserScript==
  12.  
  13. (function (global) {
  14. let isRunning = false; // Tracks whether the timer is active
  15. let speedMultiplier = localStorage.getItem("timerHookerSpeed") || 2.0; // Default speed (2x)
  16. let autoHideTimeout; // For auto-hide functionality
  17.  
  18. // Override timers with speed adjustment
  19. const overrideTimers = function (factor) {
  20. ["setTimeout", "setInterval"].forEach((method) => {
  21. window[method] = ((original) => (fn, time) => {
  22. // Exclude video-related timers
  23. const fnString = fn.toString();
  24. if (fnString.includes("playback") || fnString.includes("video")) {
  25. return original(fn, time);
  26. }
  27. return original(fn, time / factor);
  28. })(window[method]);
  29. });
  30. };
  31.  
  32. const changeTimerSpeed = function (multiplier) {
  33. speedMultiplier = multiplier;
  34. localStorage.setItem("timerHookerSpeed", multiplier);
  35. if (isRunning) overrideTimers(speedMultiplier);
  36. console.log(`[TimerHooker] Timer speed changed to x${multiplier}`);
  37. };
  38.  
  39. const createUI = function () {
  40. const style = `
  41. .timer-ball {
  42. position: fixed;
  43. bottom: 20px;
  44. right: 20px;
  45. width: 60px;
  46. height: 60px;
  47. border-radius: 50%;
  48. background-color: #4CAF50;
  49. display: flex;
  50. justify-content: center;
  51. align-items: center;
  52. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
  53. cursor: pointer;
  54. touch-action: manipulation;
  55. transition: background-color 0.3s ease;
  56. z-index: 9999; /* Ensure visibility above other elements */
  57. }
  58. .timer-ball:hover {
  59. background-color: #45A049;
  60. }
  61. .timer-symbol {
  62. font-size: 24px;
  63. color: white;
  64. font-weight: bold;
  65. }
  66. .slider-container {
  67. position: fixed;
  68. bottom: 90px;
  69. right: 20px;
  70. z-index: 9999; /* Ensure visibility above other elements */
  71. display: none;
  72. background: rgba(0, 0, 0, 0.6);
  73. padding: 10px;
  74. border-radius: 10px;
  75. box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.4);
  76. user-select: none;
  77. }
  78. .slider {
  79. width: 120px;
  80. }
  81. `;
  82.  
  83. const styleNode = document.createElement('style');
  84. styleNode.type = 'text/css';
  85. styleNode.textContent = style;
  86.  
  87. // Main ball UI
  88. const ball = document.createElement('div');
  89. ball.className = 'timer-ball';
  90. ball.innerHTML = '<div class="timer-symbol">▶</div>'; // Start symbol
  91.  
  92. // Speed adjustment slider
  93. const sliderContainer = document.createElement('div');
  94. sliderContainer.className = 'slider-container';
  95.  
  96. const slider = document.createElement('input');
  97. slider.className = 'slider';
  98. slider.type = 'range';
  99. slider.min = "1";
  100. slider.max = "200";
  101. slider.value = speedMultiplier * 100; // Scale multiplier to slider range
  102. slider.addEventListener('input', (event) => {
  103. const newSpeed = event.target.value / 100;
  104. changeTimerSpeed(newSpeed);
  105. });
  106.  
  107. sliderContainer.appendChild(slider);
  108.  
  109. ball.addEventListener('click', () => {
  110. isRunning = !isRunning;
  111. ball.querySelector('.timer-symbol').innerHTML = isRunning ? '■' : '▶'; // Toggle Start/Stop symbol
  112. overrideTimers(isRunning ? speedMultiplier : 1.0);
  113. sliderContainer.style.display = isRunning ? 'block' : 'none'; // Show/hide slider
  114. resetAutoHide(); // Reset auto-hide timer
  115. });
  116.  
  117. // Add auto-hide functionality
  118. const resetAutoHide = function () {
  119. clearTimeout(autoHideTimeout);
  120. autoHideTimeout = setTimeout(() => {
  121. if (isRunning) sliderContainer.style.display = 'none';
  122. }, 3000);
  123. };
  124.  
  125. document.body.appendChild(ball);
  126. document.body.appendChild(sliderContainer);
  127. document.head.appendChild(styleNode);
  128. };
  129.  
  130. const init = function () {
  131. console.log("[TimerHooker] Unified version activated.");
  132. createUI();
  133. overrideTimers(speedMultiplier);
  134. };
  135.  
  136. // Initialize when the DOM is loaded
  137. if (document.readyState === "complete") {
  138. init();
  139. } else {
  140. window.addEventListener("load", () => init());
  141. }
  142. })(window);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址