2020-12-11 10:11:39 +00:00
|
|
|
/**
|
|
|
|
* --- Alpine helper functions
|
|
|
|
*/
|
|
|
|
|
2020-12-11 09:46:56 +00:00
|
|
|
/**
|
|
|
|
* Set an alpine.js property
|
|
|
|
*
|
|
|
|
* @function setProp
|
|
|
|
* @param {string} key - Key of the data property
|
|
|
|
* @param {*} prop - The data property
|
|
|
|
* @param {string} selector - The jQuery selector to the root element
|
|
|
|
*/
|
|
|
|
const setProp = (key, prop, selector = '#root') => {
|
|
|
|
$(selector).get(0).__x.$data[key] = prop;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get an alpine.js property
|
|
|
|
*
|
|
|
|
* @function getProp
|
|
|
|
* @param {string} key - Key of the data property
|
|
|
|
* @param {string} selector - The jQuery selector to the root element
|
|
|
|
* @return {*} The data property
|
|
|
|
*/
|
|
|
|
const getProp = (key, selector = '#root') => {
|
|
|
|
return $(selector).get(0).__x.$data[key];
|
|
|
|
};
|
2020-12-11 10:11:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* --- Theme related functions
|
|
|
|
* Note: In the comments below we treat "theme" and "theme setting"
|
|
|
|
* differently. A theme can have only two values, either "dark" or
|
|
|
|
* "light", while a theme setting can have the third value "system".
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if the system setting prefers dark theme.
|
|
|
|
* from https://flaviocopes.com/javascript-detect-dark-mode/
|
|
|
|
*
|
|
|
|
* @function preferDarkMode
|
|
|
|
* @return {bool}
|
|
|
|
*/
|
|
|
|
const preferDarkMode = () => {
|
|
|
|
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check whether a given string represents a valid theme setting
|
|
|
|
*
|
|
|
|
* @function validThemeSetting
|
|
|
|
* @param {string} theme - The string representing the theme setting
|
|
|
|
* @return {bool}
|
|
|
|
*/
|
|
|
|
const validThemeSetting = (theme) => {
|
|
|
|
return ['dark', 'light', 'system'].indexOf(theme) >= 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load theme setting from local storage, or use 'light'
|
|
|
|
*
|
|
|
|
* @function loadThemeSetting
|
|
|
|
* @return {string} A theme setting ('dark', 'light', or 'system')
|
|
|
|
*/
|
|
|
|
const loadThemeSetting = () => {
|
|
|
|
let str = localStorage.getItem('theme');
|
2020-12-26 10:14:26 +00:00
|
|
|
if (!str || !validThemeSetting(str)) str = 'system';
|
2020-12-11 10:11:39 +00:00
|
|
|
return str;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load the current theme (not theme setting)
|
|
|
|
*
|
|
|
|
* @function loadTheme
|
|
|
|
* @return {string} The current theme to use ('dark' or 'light')
|
|
|
|
*/
|
|
|
|
const loadTheme = () => {
|
|
|
|
let setting = loadThemeSetting();
|
|
|
|
if (setting === 'system') {
|
|
|
|
setting = preferDarkMode() ? 'dark' : 'light';
|
|
|
|
}
|
|
|
|
return setting;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Save a theme setting
|
|
|
|
*
|
|
|
|
* @function saveThemeSetting
|
|
|
|
* @param {string} setting - A theme setting
|
|
|
|
*/
|
|
|
|
const saveThemeSetting = setting => {
|
2020-12-26 10:14:26 +00:00
|
|
|
if (!validThemeSetting(setting)) setting = 'system';
|
2020-12-11 10:11:39 +00:00
|
|
|
localStorage.setItem('theme', setting);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggle the current theme. When the current theme setting is 'system', it
|
|
|
|
* will be changed to either 'light' or 'dark'
|
|
|
|
*
|
|
|
|
* @function toggleTheme
|
|
|
|
*/
|
|
|
|
const toggleTheme = () => {
|
|
|
|
const theme = loadTheme();
|
|
|
|
const newTheme = theme === 'dark' ? 'light' : 'dark';
|
|
|
|
saveThemeSetting(newTheme);
|
|
|
|
setTheme(newTheme);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Apply a theme, or load a theme and then apply it
|
|
|
|
*
|
|
|
|
* @function setTheme
|
|
|
|
* @param {string?} theme - (Optional) The theme to apply. When omitted, use
|
|
|
|
* `loadTheme` to get a theme and apply it.
|
|
|
|
*/
|
|
|
|
const setTheme = (theme) => {
|
|
|
|
if (!theme) theme = loadTheme();
|
|
|
|
if (theme === 'dark') {
|
|
|
|
$('html').css('background', 'rgb(20, 20, 20)');
|
|
|
|
$('body').addClass('uk-light');
|
|
|
|
$('.ui-widget-content').addClass('dark');
|
|
|
|
} else {
|
|
|
|
$('html').css('background', '');
|
|
|
|
$('body').removeClass('uk-light');
|
|
|
|
$('.ui-widget-content').removeClass('dark');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// do it before document is ready to prevent the initial flash of white on
|
|
|
|
// most pages
|
|
|
|
setTheme();
|
|
|
|
$(() => {
|
|
|
|
// hack for the reader page
|
|
|
|
setTheme();
|
|
|
|
|
|
|
|
// on system dark mode setting change
|
|
|
|
if (window.matchMedia) {
|
|
|
|
window.matchMedia('(prefers-color-scheme: dark)')
|
|
|
|
.addEventListener('change', event => {
|
|
|
|
if (loadThemeSetting() === 'system')
|
|
|
|
setTheme(event.matches ? 'dark' : 'light');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|