Ultimate Night Mode

Change websites to pure black background with customization options

目前為 2024-09-07 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Ultimate Night Mode
  3. // @namespace (link unavailable)
  4. // @version 0.11
  5. // @description Change websites to pure black background with customization options
  6. // @match *://*/*
  7. // @grant GM_getValue
  8. // @grant GM_setValue
  9. // @grant GM_registerMenuCommand
  10. // @run-at document-start
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // Load settings
  17. const cfg = {
  18. bgColor: GM_getValue("bgColor", "#000000"),
  19. textColor: GM_getValue("textColor", "#D3D3D3"), // Light Gray
  20. linkColor: GM_getValue("linkColor", "#1E90FF"), // Bright Blue
  21. visitedLinkColor: GM_getValue("visitedLinkColor", "#551A8B"), // Purple
  22. imgBrightness: GM_getValue("imgBrightness", 0.8),
  23. imgContrast: GM_getValue("imgContrast", 1.2),
  24. bgTransparency: GM_getValue("bgTransparency", 1)
  25. };
  26.  
  27. // CSS styles
  28. const css = `
  29. html, body {
  30. background-color: ${hexToRgba(cfg.bgColor, cfg.bgTransparency)} !important;
  31. color: ${cfg.textColor} !important;
  32. }
  33. * {
  34. background-color: rgba(0, 0, 0, 0.5) !important;
  35. border-color: #444444 !important;
  36. }
  37. a {
  38. color: ${cfg.linkColor} !important;
  39. }
  40. a:visited {
  41. color: ${cfg.visitedLinkColor} !important;
  42. }
  43. img {
  44. filter: brightness(${cfg.imgBrightness}) contrast(${cfg.imgContrast});
  45. }
  46. video, .html5-video-container video {
  47. filter: none !important;
  48. }
  49. `;
  50.  
  51. // Apply styles
  52. const style = document.createElement('style');
  53. style.type = 'text/css';
  54. style.appendChild(document.createTextNode(css));
  55. document.head.appendChild(style);
  56.  
  57. // Mutation observer to handle dynamic content
  58. const observer = new MutationObserver(function() {
  59. document.documentElement.style.backgroundColor = hexToRgba(cfg.bgColor, cfg.bgTransparency);
  60. document.body.style.backgroundColor = hexToRgba(cfg.bgColor, cfg.bgTransparency);
  61. });
  62. observer.observe(document, { childList: true, subtree: true });
  63.  
  64. // Create configuration window
  65. function openConfigWindow() {
  66. const div = document.createElement('div');
  67. div.style.position = 'fixed';
  68. div.style.top = '10%';
  69. div.style.left = '50%';
  70. div.style.transform = 'translateX(-50%)';
  71. div.style.backgroundColor = '#333';
  72. div.style.color = '#fff';
  73. div.style.padding = '20px';
  74. div.style.border = '1px solid #444';
  75. div.style.zIndex = '10000';
  76. div.innerHTML = `
  77. <h2>Customize Theme</h2>
  78. <label>BG Color: <input type="color" id="bgColor" value="${cfg.bgColor}"></label><br>
  79. <label>Text: <input type="color" id="textColor" value="${cfg.textColor}"></label><br>
  80. <label>Link: <input type="color" id="linkColor" value="${cfg.linkColor}"></label><br>
  81. <label>Visited: <input type="color" id="visitedLinkColor" value="${cfg.visitedLinkColor}"></label><br>
  82. <label>Brightness: <input type="range" id="imgBrightness" min="0" max="1" step="0.1" value="${cfg.imgBrightness}"></label><br>
  83. <label>Contrast: <input type="range" id="imgContrast" min="1" max="2" step="0.1" value="${cfg.imgContrast}"></label><br>
  84. <label>Transparency: <input type="range" id="bgTransparency" min="0" max="1" step="0.1" value="${cfg.bgTransparency}"></label><br>
  85. <button id="saveConfig">Save</button>
  86. <button id="closeConfig">Close</button>
  87. `;
  88. document.body.appendChild(div);
  89.  
  90. // Sync color input and hex input
  91. document.getElementById('bgColor').addEventListener('input', function() {
  92. const hexInput = prompt("Enter hex code:", this.value);
  93. if (hexInput) this.value = hexInput;
  94. });
  95.  
  96. document.getElementById('textColor').addEventListener('input', function() {
  97. const hexInput = prompt("Enter hex code:", this.value);
  98. if (hexInput) this.value = hexInput;
  99. });
  100.  
  101. document.getElementById('linkColor').addEventListener('input', function() {
  102. const hexInput = prompt("Enter hex code:", this.value);
  103. if (hexInput) this.value = hexInput;
  104. });
  105.  
  106. document.getElementById('visitedLinkColor').addEventListener('input', function() {
  107. const hexInput = prompt("Enter hex code:", this.value);
  108. if (hexInput) this.value = hexInput;
  109. });
  110.  
  111. document.getElementById('saveConfig').addEventListener('click', () => {
  112. GM_setValue("bgColor", document.getElementById('bgColor').value);
  113. GM_setValue("textColor", document.getElementById('textColor').value);
  114. GM_setValue("linkColor", document.getElementById('linkColor').value);
  115. GM_setValue("visitedLinkColor", document.getElementById('visitedLinkColor').value);
  116. GM_setValue("imgBrightness", parseFloat(document.getElementById('imgBrightness').value));
  117. GM_setValue("imgContrast", parseFloat(document.getElementById('imgContrast').value));
  118. GM_setValue("bgTransparency", parseFloat(document.getElementById('bgTransparency').value));
  119. location.reload();
  120. });
  121.  
  122. document.getElementById('closeConfig').addEventListener('click', () => {
  123. div.remove();
  124. });
  125. }
  126.  
  127. // Convert hex to rgba
  128. function hexToRgba(hex, alpha) {
  129. let r = 0, g = 0, b = 0;
  130. if (hex.length == 4) {
  131. r = parseInt(hex[1] + hex[1], 16);
  132. g = parseInt(hex[2] + hex[2], 16);
  133. b = parseInt(hex[3] + hex[3], 16);
  134. } else if (hex.length == 7) {
  135. r = parseInt(hex[1] + hex[2], 16);
  136. g = parseInt(hex[3] + hex[4], 16);
  137. b = parseInt(hex[5] + hex[6], 16);
  138. }
  139. return `rgba(${r},${g},${b},${alpha})`;
  140. }
  141.  
  142. // Menu command to open configuration window
  143. if (typeof GM_registerMenuCommand !== "undefined") {
  144. GM_registerMenuCommand("Customize Theme", openConfigWindow, "C");
  145. }
  146. })();