Add prefers-color-scheme support (#601)

* Add prefers-color-scheme support

This should fix <https://github.com/omarroth/invidious/issues/559>.
The cookie storage format has been changed from boolean
("true"/"false") to tri-state ("dark"/"light"/""), so that users
without a cookie set will get dark mode if they have enabled the dark
theme in their operating system. The code for handling the cookie
state, along with the user's operating system theme, has been factored
out into a new function `update_mode`, which is called both at window
load and at the "storage" event listener, because the "storage" event
listener is only trigerred when a change is made to the localStorage
from another tab/window (for more info - see
<https://stackoverflow.com/a/4679754>).
This commit is contained in:
psvenk 2019-08-15 16:29:55 +00:00 committed by Omar Roth
parent 19eceb4ecc
commit f54fbd057e
24 changed files with 215 additions and 84 deletions

View file

@ -1,8 +1,8 @@
var toggle_theme = document.getElementById('toggle_theme')
var toggle_theme = document.getElementById('toggle_theme');
toggle_theme.href = 'javascript:void(0);';
toggle_theme.addEventListener('click', function () {
var dark_mode = document.getElementById('dark_theme').media == 'none';
var dark_mode = document.getElementById('dark_theme').media === 'none';
var url = '/toggle_theme?redirect=false';
var xhr = new XMLHttpRequest();
@ -11,19 +11,24 @@ toggle_theme.addEventListener('click', function () {
xhr.open('GET', url, true);
set_mode(dark_mode);
localStorage.setItem('dark_mode', dark_mode);
window.localStorage.setItem('dark_mode', dark_mode ? 'dark' : 'light');
xhr.send();
});
window.addEventListener('storage', function (e) {
if (e.key == 'dark_mode') {
var dark_mode = e.newValue === 'true';
set_mode(dark_mode);
if (e.key === 'dark_mode') {
update_mode(e.newValue);
}
});
function set_mode(bool) {
window.addEventListener('load', 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);
});
function set_mode (bool) {
document.getElementById('dark_theme').media = !bool ? 'none' : '';
document.getElementById('light_theme').media = bool ? 'none' : '';
@ -33,3 +38,21 @@ function set_mode(bool) {
toggle_theme.children[0].setAttribute('class', 'icon ion-ios-moon');
}
}
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)
}