131 lines
4.7 KiB
JavaScript
131 lines
4.7 KiB
JavaScript
// Theme system - helping visitors avoid retinal damage since 2024
|
|
(function() {
|
|
'use strict';
|
|
|
|
const html = document.documentElement;
|
|
|
|
function getStoredTheme() {
|
|
// Check everywhere for theme preferences - we're thorough like that
|
|
if (typeof localStorage !== 'undefined') {
|
|
const stored = localStorage.getItem('theme');
|
|
if (stored === 'dark' || stored === 'light') {
|
|
return stored;
|
|
}
|
|
}
|
|
|
|
const cookies = document.cookie.split(';');
|
|
for (let cookie of cookies) {
|
|
const [name, value] = cookie.trim().split('=');
|
|
if (name === 'simple_style' && (value === 'dark' || value === 'light')) {
|
|
return value;
|
|
}
|
|
if (name === 'theme' && (value === 'dark' || value === 'light')) {
|
|
return value;
|
|
}
|
|
}
|
|
|
|
// When in doubt, trust the OS (they know what they're doing... probably)
|
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
return 'dark';
|
|
}
|
|
return 'light';
|
|
}
|
|
|
|
function setThemeEverywhere(theme) {
|
|
// Scatter theme preferences like seeds in the wind - something's gotta stick
|
|
const cookieOptions = `path=/; max-age=${60 * 60 * 24 * 365 * 5}; SameSite=Lax`;
|
|
|
|
// localStorage for the modern folks
|
|
if (typeof localStorage !== 'undefined') {
|
|
localStorage.setItem('theme', theme);
|
|
}
|
|
|
|
// Cookies for SearXNG (it's picky about naming conventions)
|
|
document.cookie = `simple_style=${theme}; ${cookieOptions}`;
|
|
|
|
// More cookies - redundancy is our middle name
|
|
document.cookie = `theme=${theme}; ${cookieOptions}`;
|
|
|
|
// Data attribute for immediate gratification
|
|
html.setAttribute('data-theme', theme);
|
|
|
|
// Don't forget the icon - visual feedback matters
|
|
updateToggleIcon(theme);
|
|
}
|
|
|
|
function getTheme() {
|
|
return getStoredTheme();
|
|
}
|
|
|
|
function setTheme(theme) {
|
|
setThemeEverywhere(theme);
|
|
}
|
|
|
|
function updateToggleIcon(theme) {
|
|
const themeToggle = document.getElementById('themeToggle');
|
|
if (themeToggle) {
|
|
const moonIcon = themeToggle.querySelector('.theme-icon-moon');
|
|
const sunIcon = themeToggle.querySelector('.theme-icon-sun');
|
|
if (moonIcon && sunIcon) {
|
|
if (theme === 'dark') {
|
|
moonIcon.style.display = 'none';
|
|
sunIcon.style.display = 'block';
|
|
} else {
|
|
moonIcon.style.display = 'block';
|
|
sunIcon.style.display = 'none';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function toggleTheme() {
|
|
const currentTheme = html.getAttribute('data-theme') || getTheme();
|
|
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
|
setTheme(newTheme);
|
|
}
|
|
|
|
function initTheme() {
|
|
const theme = getTheme();
|
|
setTheme(theme);
|
|
|
|
const themeToggle = document.getElementById('themeToggle');
|
|
if (themeToggle) {
|
|
themeToggle.removeEventListener('click', toggleTheme); // No double-clicking shenanigans
|
|
themeToggle.addEventListener('click', toggleTheme);
|
|
}
|
|
}
|
|
|
|
// Dance the cookie shuffle before searching - SearXNG has opinions
|
|
const searchForm = document.getElementById('search');
|
|
if (searchForm) {
|
|
searchForm.addEventListener('submit', function(e) {
|
|
const theme = getTheme();
|
|
// Out with the old cookie
|
|
document.cookie = 'theme=; path=/; max-age=0; SameSite=Lax';
|
|
// In with SearXNG's preferred flavor
|
|
const cookieOptions = `path=/; max-age=${60 * 60 * 24 * 365 * 5}; SameSite=Lax`;
|
|
document.cookie = `simple_style=${theme}; ${cookieOptions}`;
|
|
});
|
|
}
|
|
|
|
// Get this party started
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', initTheme);
|
|
} else {
|
|
initTheme();
|
|
}
|
|
|
|
// Listen for OS theme changes - stay responsive to user preferences
|
|
if (window.matchMedia) {
|
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
if (mediaQuery.addEventListener) {
|
|
mediaQuery.addEventListener('change', function(e) {
|
|
// Only auto-switch if they haven't explicitly chosen - consent matters
|
|
if (!localStorage.getItem('theme') && !document.cookie.includes('simple_style') && !document.cookie.includes('theme=')) {
|
|
setTheme(e.matches ? 'dark' : 'light');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
})();
|