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. function darkClassObserver(mutations, observer) {
  55. for (let mutation of mutations) {
  56. if (mutation.attributeName !== "class") return;
  57. darkMode = pageHTML.classList.contains("dark");
  58. localStorage.dark = darkMode;
  59. canvas.style.filter = darkMode
  60. ? `brightness(${localStorage.canvasBrightness})` || ""
  61. : "";
  62. fixColors();
  63. grayCanvas && toggleCanvasDarkMode();
  64. }
  65. }
  66.  
  67. const gameObserver = new MutationObserver(darkClassObserver);
  68.  
  69. gameObserver.observe(pageHTML, { attributes: true });
  70.  
  71. (function addBrightnessSlider() {
  72. const sliderContainer = document
  73. .querySelector("#menuSettingsVolumeIcon")
  74. .parentNode.cloneNode(true);
  75. sliderContainer.getElementsByTagName("h5")[0].textContent =
  76. "Canvas Brightness";
  77. const icon = sliderContainer.children[0];
  78. icon.onload = () => {
  79. icon.src = "https://faust.s-ul.eu/Sa78AixS";
  80. };
  81. const slider = sliderContainer.querySelector("#menuSettingsVolume");
  82. slider.value = localStorage.canvasBrightness || 1;
  83. slider.onchange = changeBrightness;
  84.  
  85. const grayCanvasToggle = document.createElement("div");
  86. grayCanvasToggle.setAttribute(
  87. "style",
  88. "display: flex; justify-content: space-between"
  89. );
  90. const label = document.createElement("label");
  91.  
  92. label.style.fontSize = "20px";
  93. label.textContent = "Gray Canvas";
  94.  
  95. // AAAAAAAAAAAAAAA
  96. let btnSwitch = document.createElement("label");
  97. btnSwitch.setAttribute("class", "switch");
  98. let input = document.createElement("input");
  99. input.type = "checkbox";
  100. let span = document.createElement("span");
  101. span.setAttribute("class", "slider round");
  102. btnSwitch.append(input, span);
  103. input.checked = grayCanvas;
  104. input.onchange = () => {
  105. console.log(input.checked);
  106. grayCanvas = input.checked;
  107. localStorage.grayCanvas = grayCanvas;
  108. };
  109. grayCanvasToggle.append(label, btnSwitch);
  110. settingsContainer.append(sliderContainer, grayCanvasToggle);
  111. })();
  112.  
  113. (function toggleButtons() {
  114. const btn = document.querySelector("#saveButton").cloneNode();
  115. btn.style.right = "100px";
  116. btn.style.backgroundImage = "url(https://i.imgur.com/BLfKL8d.png)";
  117. btn.removeAttribute("data-toggle");
  118. btn.onclick = toggleDarkMode;
  119.  
  120. document.querySelector("#gameInterface").append(btn);
  121. })();
  122.  
  123. function changeBrightness() {
  124. canvas.style.filter = `brightness(${this.value})`;
  125. localStorage.canvasBrightness = this.value;
  126. }
  127.  
  128. function toggleDarkMode() {
  129. if (!grayCanvas) {
  130. pageHTML.classList.toggle("dark");
  131. } else {
  132. themes[darkMode ? 0 : 1].selected = true;
  133. themes.dispatchEvent(new Event("change"));
  134. }
  135. }
  136.  
  137. function toggleCanvasDarkMode() {
  138. const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  139. const data = imgData.data;
  140.  
  141. for (let i = 0; i < data.length; i += 4) {
  142. const [r, g, b] = [data[i], data[i + 1], data[i + 2]];
  143.  
  144. if (r === 255 && g === 255 && b === 255 && darkMode) {
  145. let color = 68;
  146. data[i] = color;
  147. data[i + 1] = color;
  148. data[i + 2] = color;
  149. }
  150. else if (r === 68 && g === 68 && b === 68 && !darkMode) {
  151. let color = 255;
  152. data[i] = color;
  153. data[i + 1] = color;
  154. data[i + 2] = color;
  155. }
  156. }
  157.  
  158. ctx.putImageData(imgData, 0, 0);
  159. }
  160.  
  161. function fixColors() {
  162. let names = document.getElementsByClassName("gameAvatarName");
  163.  
  164. if (!names.length)
  165. names = document.getElementsByClassName("gameSettingsAvatarName");
  166. for (let name of names) {
  167. if (darkMode && name.style.color === "black") {
  168. name.style.color = "#ccc";
  169. } else if (!darkMode && name.style.color === "rgb(204, 204, 204)") {
  170. name.style.color = "black";
  171. }
  172. }
  173. }
  174.  
  175. const colorObserver = new MutationObserver(() => {
  176. fixColors();
  177. });
  178.  
  179. colorObserver.observe(document.querySelector("#gamePlayersList"), {
  180. childList: true,
  181. });