Dark Mode+

Sketchful dark theme improvements

目前为 2020-07-27 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Dark Mode+
  3. // @match https://sketchful.io/
  4. // @grant none
  5. // @version 1.0
  6. // @description Sketchful dark theme improvements
  7. // @author bebell
  8. // @run-at document-end
  9. // jshint esversion: 6
  10. // @namespace https://greasyfork.org/users/281093
  11. // ==/UserScript==
  12.  
  13. let grayCanvas = localStorage.grayCanvas
  14. ? JSON.parse(localStorage.grayCanvas)
  15. : true;
  16.  
  17. const pageHTML = document.querySelector("html");
  18. const canvas = document.querySelector("#canvas");
  19. const ctx = canvas.getContext("2d");
  20. const themes = document.querySelector("#menuSettingsTheme");
  21. const settingsContainer = document.querySelector(
  22. "#menuSettings > div.row.justify-content-center > div"
  23. );
  24.  
  25. const styleRules = [
  26. "html.dark .table { color: white !important; }",
  27. ".table { color: black !important; }",
  28. "html.dark { background-color: #1d1f22 !important; }",
  29. "html.dark .table th, html.dark .table thead, html.dark .table td { border-color: #454d55 !important; }",
  30. ".table th, .table thead, .table td { border-color: #dee2e6 !important; }",
  31. "html.dark .table.table-striped tbody tr:nth-of-type(odd) { background-color: rgba(255,255,255,.05)!important; }",
  32. ".table.table-striped tbody tr:nth-of-type(odd) { background-color: rgba(0,0,0,.05)!important; }",
  33. "html.dark #gameChatList li:not(.chatAdmin) b { color: #BBB }",
  34. "#gameChatList li:not(.chatAdmin) b { color: black }",
  35. "html.dark .gameAvatarRank { color: #148FA2 }",
  36. "html.dark #gameWinners li b { color: white !important }",
  37. "html.dark .gameSticky { color: white !important }",
  38. "#gameSticky font { color: black!important }",
  39. "html.dark #gameSticky font { color: #eee!important }",
  40. ];
  41.  
  42. const sheet =
  43. window.document.styleSheets[window.document.styleSheets.length - 1];
  44. styleRules.forEach((rule) => sheet.insertRule(rule));
  45.  
  46. let stored = localStorage.dark;
  47. let darkMode = stored
  48. ? JSON.parse(stored)
  49. : JSON.parse(localStorage.getItem("settings")).dark;
  50.  
  51. if (darkMode) pageHTML.classList.add("dark");
  52. else pageHTML.classList.remove("dark");
  53.  
  54. canvas.style.filter = darkMode
  55. ? `brightness(${localStorage.canvasBrightness})` || ""
  56. : "";
  57.  
  58. function darkClassObserver(mutations, observer) {
  59. for (let mutation of mutations) {
  60. if (mutation.attributeName !== "class") return;
  61. darkMode = pageHTML.classList.contains("dark");
  62. localStorage.dark = darkMode;
  63. canvas.style.filter = darkMode
  64. ? `brightness(${localStorage.canvasBrightness})` || ""
  65. : "";
  66. fixColors();
  67. grayCanvas && toggleCanvasDarkMode();
  68. }
  69. }
  70.  
  71. const gameObserver = new MutationObserver(darkClassObserver);
  72.  
  73. gameObserver.observe(pageHTML, { attributes: true });
  74.  
  75. (function addBrightnessSlider() {
  76. const sliderContainer = document
  77. .querySelector("#menuSettingsVolumeIcon")
  78. .parentNode.cloneNode(true);
  79. sliderContainer.getElementsByTagName("h5")[0].textContent =
  80. "Canvas Brightness";
  81. const icon = sliderContainer.children[0];
  82. icon.onload = () => {
  83. icon.src = "https://faust.s-ul.eu/Sa78AixS";
  84. };
  85. const slider = sliderContainer.querySelector("#menuSettingsVolume");
  86. slider.value = localStorage.canvasBrightness || 1;
  87. slider.onchange = changeBrightness;
  88.  
  89. const grayCanvasToggle = document.createElement("div");
  90. grayCanvasToggle.setAttribute(
  91. "style",
  92. "display: flex; justify-content: space-between"
  93. );
  94. const label = document.createElement("label");
  95.  
  96. label.style.fontSize = "20px";
  97. label.textContent = "Gray Canvas";
  98.  
  99. // AAAAAAAAAAAAAAA
  100. let btnSwitch = document.createElement("label");
  101. btnSwitch.setAttribute("class", "switch");
  102. let input = document.createElement("input");
  103. input.type = "checkbox";
  104. let span = document.createElement("span");
  105. span.setAttribute("class", "slider round");
  106. btnSwitch.append(input, span);
  107. input.checked = grayCanvas;
  108. input.onchange = () => {
  109. console.log(input.checked);
  110. grayCanvas = input.checked;
  111. localStorage.grayCanvas = grayCanvas;
  112. };
  113. grayCanvasToggle.append(label, btnSwitch);
  114. settingsContainer.append(sliderContainer, grayCanvasToggle);
  115. })();
  116.  
  117. (function toggleButtons() {
  118. const btn = document.querySelector("#saveButton").cloneNode();
  119. btn.style.right = "100px";
  120. btn.style.backgroundImage = "url(https://i.imgur.com/BLfKL8d.png)";
  121. btn.removeAttribute("data-toggle");
  122. btn.onclick = toggleDarkMode;
  123.  
  124. document.querySelector("#gameInterface").append(btn);
  125. })();
  126.  
  127. function changeBrightness() {
  128. canvas.style.filter = `brightness(${this.value})`;
  129. localStorage.canvasBrightness = this.value;
  130. }
  131.  
  132. function toggleDarkMode() {
  133. if (!grayCanvas) {
  134. pageHTML.classList.toggle("dark");
  135. } else {
  136. themes[darkMode ? 0 : 1].selected = true;
  137. themes.dispatchEvent(new Event("change"));
  138. }
  139. }
  140.  
  141. function toggleCanvasDarkMode() {
  142. const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  143. const data = imgData.data;
  144.  
  145. for (let i = 0; i < data.length; i += 4) {
  146. const [r, g, b] = [data[i], data[i + 1], data[i + 2]];
  147.  
  148. if (r === 255 && g === 255 && b === 255 && darkMode) {
  149. let color = 68;
  150. data[i] = color;
  151. data[i + 1] = color;
  152. data[i + 2] = color;
  153. }
  154. else if (r === 68 && g === 68 && b === 68 && !darkMode) {
  155. let color = 255;
  156. data[i] = color;
  157. data[i + 1] = color;
  158. data[i + 2] = color;
  159. }
  160. }
  161.  
  162. ctx.putImageData(imgData, 0, 0);
  163. }
  164.  
  165. function fixColors() {
  166. let names = document.getElementsByClassName("gameAvatarName");
  167.  
  168. if (!names.length)
  169. names = document.getElementsByClassName("gameSettingsAvatarName");
  170. for (let name of names) {
  171. if (darkMode && name.style.color === "black") {
  172. name.style.color = "#ccc";
  173. } else if (!darkMode && name.style.color === "rgb(204, 204, 204)") {
  174. name.style.color = "black";
  175. }
  176. }
  177. }
  178.  
  179. const colorObserver = new MutationObserver(() => {
  180. fixColors();
  181. });
  182.  
  183. colorObserver.observe(document.querySelector("#gamePlayersList"), {
  184. childList: true,
  185. });