dark-mode.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /**
  2. * 对整个页面增加多种滤镜选择,比如:增强对比度、反色等
  3. * @example PageGrayTool.init('0/1/2/3/4/5')
  4. */
  5. var DarkModeMgr = (function () {
  6. let svgContent = `
  7. <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  8. <defs>
  9. <filter x="0" y="0" width="99999" height="99999" id="_fh_filter_invert">
  10. <feComponentTransfer>
  11. <feFuncR type="gamma" amplitude="-1" exponent="3" offset="1"/>
  12. <feFuncG type="gamma" amplitude="-1" exponent="3" offset="1"/>
  13. <feFuncB type="gamma" amplitude="-1" exponent="3" offset="1"/>
  14. </feComponentTransfer>
  15. </filter>
  16. <filter x="0" y="0" width="99999" height="99999" id="_fh_filter_invert_back">
  17. <feComponentTransfer>
  18. <feFuncR type="table" tableValues="1 0"/>
  19. <feFuncG type="table" tableValues="1 0"/>
  20. <feFuncB type="table" tableValues="1 0"/>
  21. </feComponentTransfer>
  22. <feComponentTransfer>
  23. <feFuncR type="gamma" exponent="1.7"/>
  24. <feFuncG type="gamma" exponent="1.7"/>
  25. <feFuncB type="gamma" exponent="1.7"/>
  26. </feComponentTransfer>
  27. </filter>
  28. <filter x="0" y="0" width="99999" height="99999" id="_fh_filter_invert_grayscale">
  29. <feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"/>
  30. <feComponentTransfer>
  31. <feFuncR type="gamma" amplitude="-1" exponent="3" offset="1"/>
  32. <feFuncG type="gamma" amplitude="-1" exponent="3" offset="1"/>
  33. <feFuncB type="gamma" amplitude="-1" exponent="3" offset="1"/>
  34. </feComponentTransfer>
  35. </filter>
  36. </defs>
  37. </svg>`;
  38. let cssTemplate = `
  39. html[dark-mode="on"] {
  40. filter: url("#_fh_filter_invert");
  41. -ms-filter: url("#_fh_filter_invert");
  42. -webkit-filter: url("#_fh_filter_invert");
  43. }
  44. html[dark-mode="on"] img[src*="jpg"],
  45. html[dark-mode="on"] img[src*="jpeg"],
  46. html[dark-mode="on"] svg image,
  47. html[dark-mode="on"] embed,
  48. html[dark-mode="on"] object,
  49. html[dark-mode="on"] video {
  50. filter: url("#_fh_filter_invert_back");
  51. -ms-filter: url("#_fh_filter_invert_back");
  52. -webkit-filter: url("#_fh_filter_invert_back");
  53. }
  54. html[dark-mode="on"] img[src*="donate.jpeg"] {
  55. filter: url("#_fh_filter_invert_grayscale");
  56. -ms-filter: url("#_fh_filter_invert_grayscale");
  57. -webkit-filter: url("#_fh_filter_invert_grayscale");
  58. }
  59. `;
  60. let isFirefox = /Firefox/.test(navigator.userAgent);
  61. function addOrUpdateExtraElements() {
  62. let style = document.getElementById('hc_style');
  63. if (!style) {
  64. let baseUrl = window.location.href.replace(window.location.hash, '');
  65. let css = cssTemplate.replace(/#/g, baseUrl + '#');
  66. style = document.createElement('style');
  67. style.id = 'hc_style';
  68. style.setAttribute('type', 'text/css');
  69. style.innerHTML = css;
  70. document.head.appendChild(style);
  71. }
  72. let bg = document.getElementById('_fh_filter_bkgnd');
  73. if (!bg) {
  74. bg = document.createElement('div');
  75. bg.id = '_fh_filter_bkgnd';
  76. bg.style.position = 'fixed';
  77. bg.style.left = '0px';
  78. bg.style.top = '0px';
  79. bg.style.right = '0px';
  80. bg.style.bottom = '0px';
  81. bg.style.zIndex = -1999999999;
  82. document.body.appendChild(bg);
  83. }
  84. bg.style.display = 'block';
  85. bg.style.background = window.getComputedStyle(document.body).background;
  86. let c = (bg.style.backgroundColor || '').replace(/\s\s*/g, '');
  87. let match = /^rgba\(([\d]+),([\d]+),([\d]+),([\d]+|[\d]*.[\d]+)\)/i.exec(c);
  88. if (match && match[4] === '0') {
  89. bg.style.backgroundColor = '#fff';
  90. }
  91. let wrap = document.getElementById('_fh_filter_svg_filters');
  92. if (!wrap) {
  93. wrap = document.createElement('span');
  94. wrap.id = '_fh_filter_svg_filters';
  95. if (!/Firefox/.test(navigator.userAgent)) {
  96. wrap.setAttribute('hidden', 'hidden');
  97. }
  98. wrap.innerHTML = svgContent;
  99. document.body.appendChild(wrap);
  100. }
  101. }
  102. function turnLight(auto) {
  103. if (isFirefox) return;
  104. document.documentElement.setAttribute('dark-mode', auto && 'on' || 'off');
  105. if (!chrome.runtime.lastError && auto) {
  106. if (window === window.top) {
  107. window.scrollBy(0, 1);
  108. window.scrollBy(0, -1);
  109. }
  110. window.setTimeout(addOrUpdateExtraElements, 2000);
  111. addOrUpdateExtraElements();
  112. let observer = new MutationObserver(function (mutations) {
  113. addOrUpdateExtraElements();
  114. });
  115. observer.observe(document.body, {attributes: true, childList: true, characterData: true});
  116. }
  117. }
  118. // 自动开关等
  119. function turnLightAuto() {
  120. if (isFirefox) return;
  121. chrome.runtime.sendMessage({
  122. type: 'fh-dynamic-any-thing'
  123. }, (params) => {
  124. let hour = new Date().getHours();
  125. let auto = localStorage.getItem('AUTO_DARK_MODE') === 'true';
  126. // 支持强制开启,优先级高
  127. let always = localStorage.getItem('ALWAYS_DARK_MODE') === 'true';
  128. let switchOn = auto && always;
  129. if (!switchOn) {
  130. // 不强制开启的情况下,看是否时间条件满足
  131. switchOn = auto && (hour >= 19 || hour < 6);
  132. }
  133. switchOn && turnLight(switchOn);
  134. return true;
  135. });
  136. }
  137. return {
  138. turnLight,
  139. turnLightAuto
  140. }
  141. })();