forked from midou/invidious
de777907f2
Themes are now controlled with a class on the body element. If a preference is set the body element will have either "dark-theme" or "light-theme" class. If no preference is set or the preference is empty the class will be "no-theme". "dark-theme" and "light-theme" are handled by darktheme.css and lighttheme.css respectively. "no-theme" is handled by default.css where depending on the value of "prefers-color-scheme" the styles corresponding to "dark-theme" or "light-theme" are applied. Unfortunately this means that both themes are duplicated, once in the theme .css and once in default.css.
85 lines
2.8 KiB
JavaScript
85 lines
2.8 KiB
JavaScript
var toggle_theme = document.getElementById('toggle_theme');
|
|
toggle_theme.href = 'javascript:void(0);';
|
|
|
|
toggle_theme.addEventListener('click', function () {
|
|
var dark_mode = document.body.classList.contains("light-theme");
|
|
|
|
var url = '/toggle_theme?redirect=false';
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.responseType = 'json';
|
|
xhr.timeout = 10000;
|
|
xhr.open('GET', url, true);
|
|
|
|
set_mode(dark_mode);
|
|
window.localStorage.setItem('dark_mode', dark_mode ? 'dark' : 'light');
|
|
|
|
xhr.send();
|
|
});
|
|
|
|
window.addEventListener('storage', function (e) {
|
|
if (e.key === 'dark_mode') {
|
|
update_mode(e.newValue);
|
|
}
|
|
});
|
|
|
|
window.addEventListener('DOMContentLoaded', function () {
|
|
window.localStorage.setItem('dark_mode', document.getElementById('dark_mode_pref').textContent);
|
|
// Update localStorage if dark mode preference changed on preferences page
|
|
update_mode(window.localStorage.dark_mode);
|
|
});
|
|
|
|
|
|
var darkScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
|
var lightScheme = window.matchMedia('(prefers-color-scheme: light)');
|
|
|
|
darkScheme.addListener(scheme_switch);
|
|
lightScheme.addListener(scheme_switch);
|
|
|
|
function scheme_switch (e) {
|
|
// ignore this method if we have a preference set
|
|
if (localStorage.getItem('dark_mode')) {
|
|
return;
|
|
}
|
|
if (e.matches) {
|
|
if (e.media.includes("dark")) {
|
|
set_mode(true);
|
|
} else if (e.media.includes("light")) {
|
|
set_mode(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
function set_mode (bool) {
|
|
if (bool) {
|
|
// dark
|
|
toggle_theme.children[0].setAttribute('class', 'icon ion-ios-sunny');
|
|
document.body.classList.remove('no-theme');
|
|
document.body.classList.remove('light-theme');
|
|
document.body.classList.add('dark-theme');
|
|
} else {
|
|
// light
|
|
toggle_theme.children[0].setAttribute('class', 'icon ion-ios-moon');
|
|
document.body.classList.remove('no-theme');
|
|
document.body.classList.remove('dark-theme');
|
|
document.body.classList.add('light-theme');
|
|
}
|
|
}
|
|
|
|
function update_mode (mode) {
|
|
if (mode === 'true' /* for backwards compatibility */ || mode === 'dark') {
|
|
// If preference for dark mode indicated
|
|
set_mode(true);
|
|
}
|
|
else if (mode === 'false' /* for backwards compaibility */ || mode === 'light') {
|
|
// If preference for light mode indicated
|
|
set_mode(false);
|
|
}
|
|
else if (document.getElementById('dark_mode_pref').textContent === '' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
// If no preference indicated here and no preference indicated on the preferences page (backend), but the browser tells us that the operating system has a dark theme
|
|
set_mode(true);
|
|
}
|
|
// else do nothing, falling back to the mode defined by the `dark_mode` preference on the preferences page (backend)
|
|
}
|
|
|
|
|