Reddit Auto Dark Mode

Automatically toggle built-in dark mode on reddit.com

  1. // ==UserScript==
  2. // @name Reddit Auto Dark Mode
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.16
  5. // @description Automatically toggle built-in dark mode on reddit.com
  6. // @author Nathaniel Wu
  7. // @match *://*.reddit.com/*
  8. // @license Apache-2.0
  9. // @supportURL https://gist.github.com/Nathaniel-Wu/f638b2fee2ece92742bfbf7d4db19f18
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15. const repeat_until_successful = (function_ptr, interval) => {
  16. if (!function_ptr())
  17. setTimeout(() => {
  18. repeat_until_successful(function_ptr, interval);
  19. }, interval);
  20. };
  21. const new_ui = getComputedStyle(document.getElementsByTagName("header")[0].firstElementChild).getPropertyValue('--newRedditTheme-body').trim() === '';
  22. const in_dark_mode = new_ui ? () => {
  23. return getComputedStyle(document.getElementsByTagName("header")[0].firstElementChild).getPropertyValue('--shreddit-content-background').trim() == '#0E1113'/*subject to change*/;
  24. } : () => {
  25. return getComputedStyle(document.getElementsByTagName("header")[0].firstElementChild).getPropertyValue('--newRedditTheme-body').trim() == "#1A1A1B"/*subject to change*/;
  26. };
  27. const switch_theme = new_ui ? () => {
  28. let preferences_button = document.querySelector('#expand-user-drawer-button' /*subject to change*/);
  29. if (!Boolean(preferences_button))
  30. return false;
  31. let preferences_panel = document.querySelector('#user-drawer-content' /*subject to change*/);
  32. if (!Boolean(preferences_panel))
  33. return false;
  34. if (preferences_panel.hidden)
  35. preferences_button.click();
  36. let night_mode_button = document.querySelector('#darkmode-list-item faceplate-switch-input[name="darkmode-switch-name"]' /*subject to change*/);
  37. if (night_mode_button == null)
  38. return false;
  39. night_mode_button.click();
  40. repeat_until_successful(() => {
  41. if (!preferences_panel.hidden) {
  42. preferences_button.click();
  43. return false;
  44. }
  45. return true;
  46. }, 500);
  47. return true;
  48. } : () => {
  49. let preferences_button = document.querySelector("#USER_DROPDOWN_ID"/*subject to change*/);
  50. if (preferences_button == null)
  51. return false;
  52. if (document.evaluate('/html/body/div/div[@role="menu"]'/*subject to change*/, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue == null) {
  53. preferences_button.click();
  54. return false;
  55. }
  56. let night_mode_button = document.evaluate('/html/body/div/div[@role="menu"]//button/span[.="Dark Mode"]/../button'/*subject to change*/, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  57. if (night_mode_button == null) {
  58. night_mode_button = document.evaluate('/html/body/div/div[@role="menu"]//button/div[.="Dark Mode"]/../button'/*subject to change*/, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  59. if (night_mode_button == null)
  60. return false;
  61. }
  62. night_mode_button.click();
  63. preferences_button.click();
  64. return true;
  65. };
  66. const setDarkMode = (on) => {
  67. if (in_dark_mode() != on)
  68. repeat_until_successful(switch_theme, 10);
  69. }
  70. const in_iframe = () => {
  71. try {
  72. return window.self !== window.top;
  73. } catch (e) {
  74. return true;
  75. }
  76. }
  77. if (!in_iframe()) {
  78. // 4/19/2025: after recent reddit update, theme switching often does not work within a short period when the website initially loads
  79. const theme_delay = 1500;
  80. if (window.matchMedia) {// if the browser/os supports system-level color scheme
  81. setTimeout(() => { setDarkMode(window.matchMedia('(prefers-color-scheme: dark)').matches); }, theme_delay);
  82. window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => setDarkMode(e.matches));
  83. } else {// otherwise use local time to decide
  84. let hour = (new Date()).getHours();
  85. setTimeout(() => { setDarkMode(hour > 18 || hour < 8); }, theme_delay);
  86. }
  87. }
  88. })();