mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-09-23 10:21:40 +00:00
Make all frontend stored preferences global
Additional change: * Delete some unused messages Bug: T341278 Depends-On: I254d7d883771dbd394ba97799d731012f7aaaefc Change-Id: Ic40da2af8ea46bd42cbebbdbceda2431bd8600ae
This commit is contained in:
parent
c8074d2355
commit
0f594e0af7
|
@ -28,7 +28,7 @@
|
|||
},
|
||||
{
|
||||
"resourceModule": "skins.vector.js",
|
||||
"maxSize": "17.0 kB"
|
||||
"maxSize": "17.5 kB"
|
||||
},
|
||||
{
|
||||
"resourceModule": "skins.vector.legacy.js",
|
||||
|
|
|
@ -42,11 +42,6 @@
|
|||
"vector-feature-custom-font-size-0-label": "Small",
|
||||
"vector-feature-custom-font-size-1-label": "Standard",
|
||||
"vector-feature-custom-font-size-2-label": "Large",
|
||||
"skin-night-mode-name": "Color",
|
||||
"skin-night-mode-description": "[Experimental version, high likelihood of experiencing issues] Reduces the light emitted by device screens.",
|
||||
"skin-night-mode-0-label": "Light",
|
||||
"skin-night-mode-1-label": "Dark",
|
||||
"skin-night-mode-2-label": "Automatic",
|
||||
"skin-theme-name": "Color",
|
||||
"skin-theme-description": "[Experimental version, high likelihood of experiencing issues] Reduces the light emitted by device screens.",
|
||||
"skin-theme-day-label": "Light",
|
||||
|
|
|
@ -59,11 +59,6 @@
|
|||
"vector-feature-custom-font-size-0-label": "Label for small (legacy) font size. An item in a list that has the title {{msg-mw|Vector-feature-custom-font-size-name}} and that includes the following items:\n* {{msg-mw|vector-feature-custom-font-size-0-label}}\n* {{msg-mw|vector-feature-custom-font-size-1-label}}\n* {{msg-mw|vector-feature-custom-font-size-2-label}}",
|
||||
"vector-feature-custom-font-size-1-label": "Label for standard font size. An item in a list that has the title {{msg-mw|Vector-feature-custom-font-size-name}} and that includes the following items:\n* {{msg-mw|vector-feature-custom-font-size-0-label}}\n* {{msg-mw|vector-feature-custom-font-size-1-label}}\n* {{msg-mw|vector-feature-custom-font-size-2-label}}",
|
||||
"vector-feature-custom-font-size-2-label": "Label for large font size. An item in a list that has the title {{msg-mw|Vector-feature-custom-font-size-name}} and that includes the following items:\n* {{msg-mw|vector-feature-custom-font-size-0-label}}\n* {{msg-mw|vector-feature-custom-font-size-1-label}}\n* {{msg-mw|vector-feature-custom-font-size-2-label}}",
|
||||
"skin-night-mode-name": "Label for setting that allows you to change theme.",
|
||||
"skin-night-mode-description": "Description for dark/night mode.",
|
||||
"skin-night-mode-0-label": "Label for light theme (standard mode).",
|
||||
"skin-night-mode-1-label": "Label for night theme (dark/night mode).",
|
||||
"skin-night-mode-2-label": "Label for night theme (automatic mode which respects any operating system setting).",
|
||||
"skin-theme-name": "Label for setting that allows you to change theme. A title of a list that includes the following items:\n* {{msg-mw|skin-theme-os-label}}\n* {{msg-mw|skin-theme-day-label}}\n* {{msg-mw|skin-theme-night-label}}",
|
||||
"skin-theme-description": "Description for dark/night mode.",
|
||||
"skin-theme-day-label": "Label for light theme (standard mode). A title of a list that has the title {{msg-mw|skin-theme-name}}, and that includes the following items:\n* {{msg-mw|skin-theme-os-label}}\n* {{msg-mw|skin-theme-day-label}}\n* {{msg-mw|skin-theme-night-label}}",
|
||||
|
|
|
@ -521,8 +521,23 @@ class Hooks implements
|
|||
*/
|
||||
public function onGetPreferences( $user, &$prefs ): void {
|
||||
$vectorPrefs = [
|
||||
Constants::PREF_KEY_LIMITED_WIDTH => [
|
||||
'type' => 'toggle',
|
||||
'label-message' => 'vector-prefs-limited-width',
|
||||
'section' => 'rendering/skin/skin-prefs',
|
||||
'help-message' => 'vector-prefs-limited-width-help',
|
||||
'hide-if' => [ '!==', 'skin', Constants::SKIN_NAME_MODERN ],
|
||||
],
|
||||
Constants::PREF_KEY_FONT_SIZE => [
|
||||
'type' => 'api'
|
||||
'type' => 'select',
|
||||
'label-message' => 'vector-feature-custom-font-size-name',
|
||||
'section' => 'rendering/skin/skin-prefs',
|
||||
'options-messages' => [
|
||||
'vector-feature-custom-font-size-0-label' => '0',
|
||||
'vector-feature-custom-font-size-1-label' => '1',
|
||||
'vector-feature-custom-font-size-2-label' => '2',
|
||||
],
|
||||
'hide-if' => [ '!==', 'skin', Constants::SKIN_NAME_MODERN ],
|
||||
],
|
||||
Constants::PREF_KEY_PAGE_TOOLS_PINNED => [
|
||||
'type' => 'api'
|
||||
|
@ -536,15 +551,17 @@ class Hooks implements
|
|||
Constants::PREF_KEY_APPEARANCE_PINNED => [
|
||||
'type' => 'api'
|
||||
],
|
||||
Constants::PREF_KEY_LIMITED_WIDTH => [
|
||||
'type' => 'toggle',
|
||||
'label-message' => 'vector-prefs-limited-width',
|
||||
'section' => 'rendering/skin/skin-prefs',
|
||||
'help-message' => 'vector-prefs-limited-width-help',
|
||||
'hide-if' => [ '!==', 'skin', Constants::SKIN_NAME_MODERN ],
|
||||
],
|
||||
Constants::PREF_KEY_NIGHT_MODE => [
|
||||
'type' => 'api'
|
||||
'type' => 'select',
|
||||
'label-message' => 'skin-theme-name',
|
||||
'help-message' => 'skin-theme-description',
|
||||
'section' => 'rendering/skin/skin-prefs',
|
||||
'options-messages' => [
|
||||
'skin-theme-day-label' => 'day',
|
||||
'skin-theme-night-label' => 'night',
|
||||
'skin-theme-os-label' => 'os',
|
||||
],
|
||||
'hide-if' => [ '!==', 'skin', Constants::SKIN_NAME_MODERN ],
|
||||
],
|
||||
];
|
||||
$prefs += $vectorPrefs;
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
* @property {string} [type] defaults to radio. Supported: radio, switch
|
||||
* @property {Function} [callback] callback executed after a client preference has been modified.
|
||||
*/
|
||||
let /** @type {MwApi} */ api;
|
||||
|
||||
/**
|
||||
* @typedef {Object} UserPreferencesApi
|
||||
* @property {Function} saveOptions
|
||||
*/
|
||||
/**
|
||||
* @typedef {Object} PreferenceOption
|
||||
* @property {string} label
|
||||
|
@ -49,8 +53,9 @@ function getVisibleClientPreferences( config ) {
|
|||
* @param {string} featureName
|
||||
* @param {string} value
|
||||
* @param {Record<string,ClientPreference>} config
|
||||
* @param {UserPreferencesApi} [userPreferences]
|
||||
*/
|
||||
function toggleDocClassAndSave( featureName, value, config ) {
|
||||
function toggleDocClassAndSave( featureName, value, config, userPreferences ) {
|
||||
const pref = config[ featureName ];
|
||||
const callback = pref.callback || ( () => {} );
|
||||
if ( mw.user.isNamed() ) {
|
||||
|
@ -64,8 +69,8 @@ function toggleDocClassAndSave( featureName, value, config ) {
|
|||
document.documentElement.classList.add( `${ featureName }-clientpref-${ value }` );
|
||||
// Ideally this should be taken care of via a single core helper function.
|
||||
mw.util.debounce( () => {
|
||||
api = api || new mw.Api();
|
||||
api.saveOption( pref.preferenceKey, value ).then( () => {
|
||||
userPreferences = userPreferences || new mw.Api();
|
||||
userPreferences.saveOptions( { [ pref.preferenceKey ]: value } ).then( () => {
|
||||
callback();
|
||||
} );
|
||||
}, 100 )();
|
||||
|
@ -142,8 +147,9 @@ function makeExclusionNotice( featureName ) {
|
|||
* @param {string} value
|
||||
* @param {string} currentValue
|
||||
* @param {Record<string,ClientPreference>} config
|
||||
* @param {UserPreferencesApi} userPreferences
|
||||
*/
|
||||
function appendRadioToggle( parent, featureName, value, currentValue, config ) {
|
||||
function appendRadioToggle( parent, featureName, value, currentValue, config, userPreferences ) {
|
||||
const input = makeInputElement( 'radio', featureName, value );
|
||||
input.classList.add( 'cdx-radio__input' );
|
||||
if ( currentValue === value ) {
|
||||
|
@ -165,7 +171,7 @@ function appendRadioToggle( parent, featureName, value, currentValue, config ) {
|
|||
container.appendChild( label );
|
||||
parent.appendChild( container );
|
||||
input.addEventListener( 'change', () => {
|
||||
toggleDocClassAndSave( featureName, value, config );
|
||||
toggleDocClassAndSave( featureName, value, config, userPreferences );
|
||||
} );
|
||||
}
|
||||
|
||||
|
@ -175,8 +181,9 @@ function appendRadioToggle( parent, featureName, value, currentValue, config ) {
|
|||
* @param {HTMLElement} labelElement
|
||||
* @param {string} currentValue
|
||||
* @param {Record<string,ClientPreference>} config
|
||||
* @param {UserPreferencesApi} userPreferences
|
||||
*/
|
||||
function appendToggleSwitch( form, featureName, labelElement, currentValue, config ) {
|
||||
function appendToggleSwitch( form, featureName, labelElement, currentValue, config, userPreferences ) {
|
||||
const input = makeInputElement( 'checkbox', featureName, currentValue );
|
||||
input.classList.add( 'cdx-toggle-switch__input' );
|
||||
const switcher = document.createElement( 'span' );
|
||||
|
@ -192,7 +199,7 @@ function appendToggleSwitch( form, featureName, labelElement, currentValue, conf
|
|||
toggleSwitch.appendChild( switcher );
|
||||
toggleSwitch.appendChild( label );
|
||||
input.addEventListener( 'change', () => {
|
||||
toggleDocClassAndSave( featureName, input.checked ? '1' : '0', config );
|
||||
toggleDocClassAndSave( featureName, input.checked ? '1' : '0', config, userPreferences );
|
||||
} );
|
||||
form.appendChild( toggleSwitch );
|
||||
}
|
||||
|
@ -221,9 +228,10 @@ const getFeatureLabelMsg = ( featureName ) => mw.message( `${ featureName }-name
|
|||
*
|
||||
* @param {string} featureName
|
||||
* @param {Record<string,ClientPreference>} config
|
||||
* @param {UserPreferencesApi} userPreferences
|
||||
* @return {Element|null}
|
||||
*/
|
||||
function makeControl( featureName, config ) {
|
||||
function makeControl( featureName, config, userPreferences ) {
|
||||
const pref = config[ featureName ];
|
||||
const isExcluded = isFeatureExcluded( featureName );
|
||||
|
||||
|
@ -242,13 +250,13 @@ function makeControl( featureName, config ) {
|
|||
switch ( type ) {
|
||||
case 'radio':
|
||||
pref.options.forEach( ( value ) => {
|
||||
appendRadioToggle( form, featureName, value, String( currentValue ), config );
|
||||
appendRadioToggle( form, featureName, value, String( currentValue ), config, userPreferences );
|
||||
} );
|
||||
break;
|
||||
case 'switch': {
|
||||
const labelElement = document.createElement( 'label' );
|
||||
labelElement.textContent = getFeatureLabelMsg( featureName ).text();
|
||||
appendToggleSwitch( form, featureName, labelElement, String( currentValue ), config );
|
||||
appendToggleSwitch( form, featureName, labelElement, String( currentValue ), config, userPreferences );
|
||||
break;
|
||||
} default:
|
||||
throw new Error( 'Unknown client preference! Only switch or radio are supported.' );
|
||||
|
@ -266,8 +274,9 @@ function makeControl( featureName, config ) {
|
|||
* @param {Element} parent
|
||||
* @param {string} featureName
|
||||
* @param {Record<string,ClientPreference>} config
|
||||
* @param {UserPreferencesApi} userPreferences
|
||||
*/
|
||||
function makeClientPreference( parent, featureName, config ) {
|
||||
function makeClientPreference( parent, featureName, config, userPreferences ) {
|
||||
const labelMsg = getFeatureLabelMsg( featureName );
|
||||
// If the user is not debugging messages and no language exists,
|
||||
// exit as its a hidden client preference.
|
||||
|
@ -305,7 +314,7 @@ function makeClientPreference( parent, featureName, config ) {
|
|||
}
|
||||
|
||||
parent.appendChild( portlet );
|
||||
const row = makeControl( featureName, config );
|
||||
const row = makeControl( featureName, config, userPreferences );
|
||||
if ( row ) {
|
||||
const tmp = mw.util.addPortletLink( id, '', '' );
|
||||
// create a dummy link
|
||||
|
@ -324,16 +333,18 @@ function makeClientPreference( parent, featureName, config ) {
|
|||
*
|
||||
* @param {string} selector of element to fill with client preferences
|
||||
* @param {Record<string,ClientPreference>} config
|
||||
* @param {UserPreferencesApi} [userPreferences]
|
||||
* @return {Promise<Node>}
|
||||
*/
|
||||
function render( selector, config ) {
|
||||
function render( selector, config, userPreferences ) {
|
||||
const node = document.querySelector( selector );
|
||||
if ( !node ) {
|
||||
return Promise.reject();
|
||||
}
|
||||
return new Promise( ( resolve ) => {
|
||||
getVisibleClientPreferences( config ).forEach( ( pref ) => {
|
||||
makeClientPreference( node, pref, config );
|
||||
userPreferences = userPreferences || new mw.Api();
|
||||
makeClientPreference( node, pref, config, userPreferences );
|
||||
} );
|
||||
mw.requestIdleCallback( () => {
|
||||
resolve( node );
|
||||
|
@ -345,8 +356,9 @@ function render( selector, config ) {
|
|||
* @param {string} clickSelector what to click
|
||||
* @param {string} renderSelector where to render
|
||||
* @param {Record<string,ClientPreference>} config
|
||||
* @param {UserPreferencesApi} [userPreferences]
|
||||
*/
|
||||
function bind( clickSelector, renderSelector, config ) {
|
||||
function bind( clickSelector, renderSelector, config, userPreferences ) {
|
||||
let enhanced = false;
|
||||
const chk = /** @type {HTMLInputElement} */ (
|
||||
document.querySelector( clickSelector )
|
||||
|
@ -354,15 +366,18 @@ function bind( clickSelector, renderSelector, config ) {
|
|||
if ( !chk ) {
|
||||
return;
|
||||
}
|
||||
if ( !userPreferences ) {
|
||||
userPreferences = new mw.Api();
|
||||
}
|
||||
if ( chk.checked ) {
|
||||
render( renderSelector, config );
|
||||
render( renderSelector, config, userPreferences );
|
||||
enhanced = true;
|
||||
} else {
|
||||
chk.addEventListener( 'input', () => {
|
||||
if ( enhanced ) {
|
||||
return;
|
||||
}
|
||||
render( renderSelector, config );
|
||||
render( renderSelector, config, userPreferences );
|
||||
enhanced = true;
|
||||
} );
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
const userPreferences = require( './userPreferences.js' );
|
||||
|
||||
/**
|
||||
* T365083 - Disable night mode if night mode gadget is enabled
|
||||
*
|
||||
|
@ -60,8 +62,7 @@ function alterDisableLink( container ) {
|
|||
disableOptions[ `gadget-${ gadgetName }` ] = 0;
|
||||
} );
|
||||
|
||||
const api = new mw.Api();
|
||||
api.saveOptions( disableOptions ).then( () => {
|
||||
userPreferences.saveOptions( disableOptions ).then( () => {
|
||||
window.location.reload();
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @interface MwApi */
|
||||
|
||||
let /** @type {MwApi} */ api;
|
||||
const debounce = require( /** @type {string} */ ( 'mediawiki.util' ) ).debounce;
|
||||
const userPreferences = require( './userPreferences.js' );
|
||||
|
||||
/**
|
||||
* Saves preference to user preferences and/or cookies.
|
||||
|
@ -24,8 +24,9 @@ function save( feature, enabled ) {
|
|||
}
|
||||
} else {
|
||||
debounce( () => {
|
||||
api = api || new mw.Api();
|
||||
api.saveOption( 'vector-' + feature, enabled ? 1 : 0 );
|
||||
userPreferences.saveOptions( {
|
||||
[ `vector-${ feature }` ]: enabled ? 1 : 0
|
||||
} );
|
||||
}, 500 )();
|
||||
}
|
||||
}
|
||||
|
|
17
resources/skins.vector.js/userPreferences.js
Normal file
17
resources/skins.vector.js/userPreferences.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
let /** @type {MwApi} */ api;
|
||||
|
||||
/**
|
||||
* @param {Object<string,string|number>} options
|
||||
* @return {JQuery.Promise<Object>}
|
||||
*/
|
||||
function saveOptions( options ) {
|
||||
api = api || new mw.Api();
|
||||
// @ts-ignore
|
||||
return api.saveOptions( options, {
|
||||
global: 'update'
|
||||
} );
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
saveOptions
|
||||
};
|
|
@ -415,6 +415,7 @@
|
|||
"resources/skins.vector.js/sectionObserver.js",
|
||||
"resources/skins.vector.js/deferUntilFrame.js",
|
||||
"resources/skins.vector.js/pinnableElement.js",
|
||||
"resources/skins.vector.js/userPreferences.js",
|
||||
"resources/skins.vector.js/features.js",
|
||||
"resources/skins.vector.js/limitedWidthToggle.js",
|
||||
"resources/skins.vector.js/popupNotification.js",
|
||||
|
|
Loading…
Reference in a new issue