refactor(core): remove duplicated auto theme handling

Refactor auto theme handling into inline script since theme.js is basically duplicated code
at this point. Also add the event listener whenever auto theme is set.

Closes: #461
This commit is contained in:
alistair3149 2022-05-20 17:33:10 -04:00
parent 71999f8838
commit da619c793b
No known key found for this signature in database
GPG key ID: 94D081060FD3DD9C
5 changed files with 88 additions and 110 deletions

View file

@ -75,7 +75,7 @@ class SkinHooks implements SkinPageReadyConfigHook, BeforePageDisplayHook {
$script = sprintf(
'<script%s>%s</script>',
$nonce !== false ? sprintf( ' nonce="%s"', $nonce ) : '',
'window.applyPref=()=>{const a="skin-citizen-",b={fontsize:"font-size",pagewidth:"--width-layout",lineheight:"--line-height"},c=()=>["auto","dark","light"].map(b=>a+b),d=a=>{let b=document.getElementById("citizen-style");null===b&&(b=document.createElement("style"),b.setAttribute("id","citizen-style"),document.head.appendChild(b)),b.textContent=`:root{${a}}`};try{const e=window.localStorage.getItem("skin-citizen-theme");let f="";if(null!==e){const b=document.documentElement;b.classList.remove(...c(a)),b.classList.add(a+e)}for(const[c,d]of Object.entries(b)){const b=window.localStorage.getItem(a+c);null!==b&&(f+=`${d}:${b};`)}f&&d(f)}catch(a){}},(()=>{const a="skin-citizen-theme";if("auto"===window.localStorage.getItem("skin-citizen-theme")){const b=window.matchMedia("(prefers-color-scheme: dark)")?"dark":"light";window.localStorage.setItem(a,b),window.applyPref(),window.localStorage.setItem(a,"auto")}else window.applyPref()})();'
'window.applyPref=()=>{const a="skin-citizen-",b="skin-citizen-theme",c=a=>window.localStorage.getItem(a),d=c("skin-citizen-theme"),e=()=>{const d={fontsize:"font-size",pagewidth:"--width-layout",lineheight:"--line-height"},e=()=>["auto","dark","light"].map(b=>a+b),f=a=>{let b=document.getElementById("citizen-style");null===b&&(b=document.createElement("style"),b.setAttribute("id","citizen-style"),document.head.appendChild(b)),b.textContent=`:root{${a}}`};try{const g=c(b);let h="";if(null!==g){const b=document.documentElement;b.classList.remove(...e(a)),b.classList.add(a+g)}for(const[b,e]of Object.entries(d)){const d=c(a+b);null!==d&&(h+=`${e}:${d};`)}h&&f(h)}catch(a){}};if("auto"===d||null===d){const a=window.matchMedia("(prefers-color-scheme: dark)"),c=a.matches?"dark":"light",d=(a,b)=>window.localStorage.setItem(a,b);d(b,c),e(),a.addEventListener("change",()=>{e()}),d(b,"auto")}else e()},(()=>{window.applyPref()})();'
);
$out->addHeadItem( 'skin.citizen.inline', $script );

View file

@ -7,7 +7,17 @@
* Mangle using https://jscompress.com/
*/
window.applyPref = () => {
const prefix = 'skin-citizen-';
const
prefix = 'skin-citizen-',
themeKey = prefix + 'theme';
const getStorage = ( key ) => {
return window.localStorage.getItem( key );
};
const targetTheme = getStorage( themeKey );
const apply = () => {
const cssProps = {
fontsize: 'font-size',
pagewidth: '--width-layout',
@ -34,7 +44,7 @@ window.applyPref = () => {
};
try {
const theme = window.localStorage.getItem( prefix + 'theme' );
const theme = getStorage( themeKey );
let cssDeclaration = '';
@ -54,7 +64,7 @@ window.applyPref = () => {
// Apply pref by adding CSS to root
/* eslint-disable-next-line compat/compat */
for ( const [ key, property ] of Object.entries( cssProps ) ) {
const value = window.localStorage.getItem( prefix + key );
const value = getStorage( prefix + key );
if ( value !== null ) {
cssDeclaration += `${property}:${value};`;
@ -66,19 +76,33 @@ window.applyPref = () => {
}
} catch ( e ) {
}
};
// Set up auto theme based on prefers-color-scheme
if ( targetTheme === 'auto' || targetTheme === null ) {
const prefersDark = window.matchMedia( '(prefers-color-scheme: dark)' );
const autoTheme = prefersDark.matches ? 'dark' : 'light';
const setStorage = ( key, value ) => {
return window.localStorage.setItem( key, value );
};
// Set to the right theme temporarily
setStorage( themeKey, autoTheme );
apply();
// Attach listener for future changes
prefersDark.addEventListener( 'change', () => {
apply();
} );
// Reset back to auto
setStorage( themeKey, 'auto' );
} else {
apply();
}
};
( () => {
const themeId = 'skin-citizen-theme';
// Set up auto theme based on prefers-color-scheme
if ( window.localStorage.getItem( themeId ) === 'auto' ) {
const autoTheme = window.matchMedia( '(prefers-color-scheme: dark)' ) ? 'dark' : 'light';
// Set to the right theme temporarily
window.localStorage.setItem( themeId, autoTheme );
window.applyPref();
// Reset back to auto
window.localStorage.setItem( themeId, 'auto' );
} else {
window.applyPref();
}
} )();

View file

@ -85,14 +85,11 @@ function onTitleHidden( document ) {
* @return {void}
*/
function main( window ) {
const
theme = require( './theme.js' ),
search = require( './search.js' );
const search = require( './search.js' );
const tocContainer = document.getElementById( 'toc' );
enableCssAnimations( window.document );
theme.init( window );
search.init( window );
onTitleHidden( window.document );

View file

@ -1,42 +0,0 @@
/**
* @param {Window} window
* @return {void}
*/
function initThemeSettings( window ) {
const setLocalStorage = ( themeName ) => {
try {
// eslint-disable-next-line indent
localStorage.setItem( 'skin-citizen-theme', themeName );
} catch ( e ) {}
};
const prefersDark = window.matchMedia( '(prefers-color-scheme: dark)' ),
applyTheme = () => {
window.applyPref();
// So that theme is applied but localStorage keeps the auto config
setLocalStorage( 'auto' );
};
// Monitor prefers-color-scheme changes
prefersDark.addEventListener( 'change', ( event ) => {
setLocalStorage( event.matches ? 'dark' : 'light' );
applyTheme();
} );
}
/**
* @param {Window} window
* @return {void}
*/
function initTheme( window ) {
if ( typeof window.mw !== 'undefined' ) {
const theme = window.localStorage.getItem( 'skin-citizen-theme' );
if ( theme === null || theme === 'auto' ) {
initThemeSettings( window );
}
}
}
module.exports = {
init: initTheme
};

View file

@ -191,8 +191,7 @@
"resources/skins.citizen.scripts/scrollObserver.js",
"resources/skins.citizen.scripts/sectionObserver.js",
"resources/skins.citizen.scripts/search.js",
"resources/skins.citizen.scripts/tableOfContents.js",
"resources/skins.citizen.scripts/theme.js"
"resources/skins.citizen.scripts/tableOfContents.js"
],
"targets": [
"desktop",