User:Monster Domosed/common.js: Difference between revisions

No edit summary
No edit summary
Line 1: Line 1:
(function () {
'use strict';
const CONFIG = {
optionKey: 'gadget-theme',
cookieKey: 'theme',
className: 'theme-light',
toggleId: 'pt-theme-toggle'
};
// Sun = shown in dark mode (click to switch to light)
// Moon = shown in light mode (click to switch to dark)
const ICONS = {
sun: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z" /></svg>',
moon: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z" /></svg>'
};
function Storage() {
function loggedIn() {
return mw.user.isNamed();
}
// true = light theme, false = dark (default)
function getState() {
return mw.user.options.get(CONFIG.optionKey) == 1;
}
function save(value) {
if (loggedIn()) {
return new mw.Api().saveOption(CONFIG.optionKey, value ? 1 : 0);
}
mw.cookie.set(CONFIG.cookieKey, value ? '1' : '0', {
expires: 365 * 86400,
prefix: ''
});
return $.Deferred().resolve().promise();
}
function readCookieFallback(defaultValue) {
if (loggedIn()) return defaultValue;
return mw.cookie.get(CONFIG.cookieKey, '', defaultValue ? '1' : '0') === '1';
}
return {
loggedIn,
getState,
save,
readCookieFallback
};
}
function View() {
function iconFor(light) {
return light ? ICONS.moon : ICONS.sun;
}
function labelFor(light) {
return light ? 'Switch to dark theme' : 'Switch to light theme';
}
function apply(light) {
document.documentElement.classList.toggle(CONFIG.className, light);
const a = document.querySelector('#' + CONFIG.toggleId + ' a');
if (a) {
a.innerHTML = iconFor(light);
a.setAttribute('aria-label', labelFor(light));
a.title = labelFor(light);
}
}
function createToggle(onToggle, getState) {
function findTarget() {
return document.querySelector('#p-personal ul');
}
const ul = findTarget();
if (!ul) {
setTimeout(function () {
createToggle(onToggle, getState);
}, 300);
return;
}
if (document.getElementById(CONFIG.toggleId)) return;
const light = getState();
const li = document.createElement('li');
li.id = CONFIG.toggleId;
const a = document.createElement('a');
a.href = '#';
a.innerHTML = iconFor(light);
a.setAttribute('aria-label', labelFor(light));
a.title = labelFor(light);
a.addEventListener('click', function (e) {
e.preventDefault();
onToggle();
});
li.appendChild(a);
ul.insertBefore(li, ul.firstChild);
}
return {
apply,
createToggle
};
}
function Controller() {
const store = Storage();
const view = View();
let state = store.getState();
function set(next) {
state = next;
view.apply(state);
store.save(state).fail(function () {
mw.notify('Could not save theme preference.', {
title: 'Theme toggle',
type: 'warn',
tag: 'themeToggle'
});
});
}
function toggle() {
set(!state);
}
function init() {
if (!store.loggedIn()) {
state = store.readCookieFallback(state);
}
view.apply(state);
view.createToggle(toggle, function () {
return state;
});
}
return {
init
};
}
$(function () {
new Controller().init();
});
})();
/*  Patch Formatter  */
/*  Patch Formatter  */
( function () {
( function () {