Dark Mode Toggle

dark mode using inversion, double-hit Esc for toggle button

目前为 2025-03-16 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Dark Mode Toggle
  3. // @namespace https://github.com/Alistair1231/my-userscripts/
  4. // @version 0.2.1
  5. // @description dark mode using inversion, double-hit Esc for toggle button
  6. // @author Alistair1231
  7. // @license GPL-3.0
  8. // @match *://*/*
  9. // @run-at document-start
  10. // @grant GM.addStyle
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. "use strict";
  15.  
  16. const CONFIG = {
  17. inversionPercent: 90,
  18. mediaInversionPercent: 100,
  19. uiTimeout: 3000,
  20. doublePressDelay: 500,
  21. };
  22.  
  23. let isActive = false;
  24. let lastEscPress = 0;
  25. let uiTimeout;
  26. let btn = null;
  27. const style = `
  28. html {
  29. -webkit-filter: invert(${CONFIG.inversionPercent}%);
  30. filter: invert(${CONFIG.inversionPercent}%);
  31. }
  32. img, video, iframe, object, embed, canvas, svg {
  33. -webkit-filter: invert(${CONFIG.mediaInversionPercent}%);
  34. filter: invert(${CONFIG.mediaInversionPercent}%);
  35. }
  36. `;
  37.  
  38. // Run initial setup immediately
  39. init();
  40.  
  41. // Wait for DOM to be ready before creating the button
  42. document.addEventListener("DOMContentLoaded", () => {
  43. createButton();
  44. });
  45.  
  46. // !
  47. // ! Functions
  48. // !
  49. // Function to create the toggle button
  50. function createButton() {
  51. if (!btn) {
  52. btn = document.createElement("button");
  53. btn.textContent = "🌓 Toggle Dark Mode";
  54. btn.style.cssText = `
  55. position: fixed;
  56. bottom: 20px;
  57. right: 20px;
  58. z-index: 2147483647 !important;
  59. padding: 8px 12px;
  60. cursor: pointer;
  61. border-radius: 4px;
  62. background: #fff;
  63. color: #333;
  64. box-shadow: 0 2px 5px rgba(0,0,0,0.2);
  65. opacity: 0;
  66. visibility: hidden;
  67. transition: opacity 0.3s ease;
  68. `;
  69. btn.addEventListener("click", () => {
  70. if (window.localStorage.darkMode === "true") {
  71. window.localStorage.darkMode = false;
  72. } else if (window.localStorage.darkMode === "false") {
  73. window.localStorage.darkMode = true;
  74. } else {
  75. window.localStorage.darkMode = true;
  76. }
  77. window.location.reload();
  78. });
  79. document.body.appendChild(btn);
  80. }
  81. }
  82.  
  83. function handleEscPress() {
  84. const now = Date.now();
  85. if (now - lastEscPress < CONFIG.doublePressDelay) {
  86. showToggleUI();
  87. }
  88. lastEscPress = now;
  89. }
  90.  
  91. function showToggleUI() {
  92. clearTimeout(uiTimeout);
  93. if (btn) {
  94. btn.style.visibility = "visible";
  95. btn.style.opacity = "1";
  96. }
  97. uiTimeout = setTimeout(() => {
  98. if (btn) {
  99. btn.style.opacity = "0";
  100. setTimeout(() => {
  101. btn.style.visibility = "hidden";
  102. }, 300);
  103. }
  104. }, CONFIG.uiTimeout);
  105. }
  106.  
  107. // Initial setup that can run immediately
  108. function init() {
  109. // Add keydown listener for Escape and Alt+Shift+D
  110. document.addEventListener("keydown", (e) => {
  111. if (e.key === "Escape") handleEscPress();
  112. });
  113.  
  114. // Check localStorage and apply dark mode if needed
  115. if (window.localStorage.darkMode === "true") {
  116. GM.addStyle(style);
  117. }
  118. }
  119. })();