| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- import Foundation
- enum RedditThemeStyle {
- static func earlyInjectionScript(isDarkMode: Bool) -> String {
- """
- (function() {
- const wantDark = \(isDarkMode ? "true" : "false");
- window.__reddoraTheme = { wantsDark: wantDark };
- const installMatchMediaOverride = (wantsDark) => {
- if (window.__reddoraTheme.matchMediaInstalled) return;
- const original = window.matchMedia.bind(window);
- window.matchMedia = function(query) {
- const result = original(query);
- if (typeof query === 'string' && query.includes('prefers-color-scheme')) {
- const matches = query.includes('dark') ? wantsDark : !wantsDark;
- return {
- matches,
- media: query,
- onchange: null,
- addEventListener: (...args) => result.addEventListener(...args),
- removeEventListener: (...args) => result.removeEventListener(...args),
- dispatchEvent: (...args) => result.dispatchEvent(...args),
- };
- }
- return result;
- };
- window.__reddoraTheme.matchMediaInstalled = true;
- };
- installMatchMediaOverride(wantDark);
- })();
- """
- }
- static func syncScript(isDarkMode: Bool) -> String {
- """
- (function() {
- const wantDark = \(isDarkMode ? "true" : "false");
- window.__reddoraTheme = window.__reddoraTheme || {};
- window.__reddoraTheme.wantsDark = wantDark;
- const installMatchMediaOverride = (wantsDark) => {
- const original = window.matchMedia.bind(window);
- window.matchMedia = function(query) {
- const result = original(query);
- if (typeof query === 'string' && query.includes('prefers-color-scheme')) {
- const matches = query.includes('dark') ? wantsDark : !wantsDark;
- return {
- matches,
- media: query,
- onchange: null,
- addEventListener: (...args) => result.addEventListener(...args),
- removeEventListener: (...args) => result.removeEventListener(...args),
- dispatchEvent: (...args) => result.dispatchEvent(...args),
- };
- }
- return result;
- };
- window.__reddoraTheme.matchMediaInstalled = true;
- };
- installMatchMediaOverride(wantDark);
- const isDrawerHidden = (element) => !element || (element.offsetWidth === 0 && element.offsetHeight === 0);
- const isRedditDarkModeActive = () => {
- const header = document.querySelector('header');
- const themedNode = header?.firstElementChild;
- if (themedNode) {
- const background = getComputedStyle(themedNode)
- .getPropertyValue('--shreddit-content-background')
- .trim()
- .toLowerCase();
- if (background === '#0e1113' || background === '#1a1a1b') return true;
- if (background === '#ffffff' || background === '#fff') return false;
- }
- const root = document.documentElement;
- if (root.classList.contains('theme-dark')) return true;
- if (root.classList.contains('theme-light')) return false;
- return window.matchMedia('(prefers-color-scheme: dark)').matches;
- };
- const toggleViaDrawer = () => {
- const drawerButton = document.querySelector('#expand-user-drawer-button');
- const drawer = document.querySelector('#user-drawer-content');
- const switchInput = document.querySelector(
- '#darkmode-list-item faceplate-switch-input[name="darkmode-switch-name"]'
- );
- if (!drawerButton || !drawer || !switchInput) return false;
- const drawerWasHidden = isDrawerHidden(drawer);
- if (drawerWasHidden) drawerButton.click();
- const isChecked = switchInput.checked === true
- || switchInput.getAttribute('checked') !== null
- || switchInput.getAttribute('aria-checked') === 'true';
- if (isChecked !== wantDark) {
- switchInput.click();
- }
- if (drawerWasHidden) {
- setTimeout(() => {
- if (!isDrawerHidden(drawer)) drawerButton.click();
- }, 250);
- }
- return true;
- };
- const syncViaAPI = async () => {
- try {
- const response = await fetch('/api/v1/me/prefs', {
- method: 'PATCH',
- headers: { 'Content-Type': 'application/json' },
- credentials: 'same-origin',
- body: JSON.stringify({ nightmode: wantDark }),
- });
- return response.ok;
- } catch {
- return false;
- }
- };
- const run = async () => {
- const current = isRedditDarkModeActive();
- if (current === wantDark) return;
- if (toggleViaDrawer()) return;
- const updated = await syncViaAPI();
- if (updated) {
- window.location.reload();
- }
- };
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', () => run(), { once: true });
- } else {
- run();
- }
- })();
- """
- }
- }
|