mediawiki-skins-Vector/resources/skins.vector.js/features.js
Jon Robson acb79c5e1b Improve documentation for how feature manager classes work.
This changes nothing about the existing classes, it just improves
how they are documented.

The FIXME comment was making things confusing.

Make sure every feature class is accounted for and audited and
throw a RuntimeException if we forget to document it.

Change-Id: I9d8f6553fe6b8c2ae80d8b2490c8895a8334a537
2024-08-08 20:19:48 +00:00

108 lines
3.4 KiB
JavaScript

/** @interface MwApi */
const debounce = require( /** @type {string} */ ( 'mediawiki.util' ) ).debounce;
const userPreferences = require( './userPreferences.js' );
/**
* Saves preference to user preferences and/or cookies.
*
* @param {string} feature
* @param {boolean} enabled
*/
function save( feature, enabled ) {
if ( !mw.user.isNamed() ) {
switch ( feature ) {
case 'toc-pinned':
case 'limited-width':
case 'appearance-pinned':
// Save the setting under the new system
mw.user.clientPrefs.set( `vector-feature-${ feature }`, enabled ? '1' : '0' );
break;
default:
// not a supported anonymous preference
break;
}
} else {
debounce( () => {
userPreferences.saveOptions( {
[ `vector-${ feature }` ]: enabled ? 1 : 0
} );
}, 500 )();
}
}
/**
* @param {string} name feature name
* @param {boolean} [override] option to force enabled or disabled state.
* @param {boolean} [isNotClientPreference] the feature is not a client preference,
* so does not persist for logged out users.
* @return {boolean} The new feature state (false=disabled, true=enabled).
* @throws {Error} if unknown feature toggled.
*/
function toggleDocClasses( name, override, isNotClientPreference ) {
const suffixEnabled = isNotClientPreference ? 'enabled' : 'clientpref-1';
const suffixDisabled = isNotClientPreference ? 'disabled' : 'clientpref-0';
const featureClassEnabled = `vector-feature-${ name }-${ suffixEnabled }`,
classList = document.documentElement.classList,
featureClassDisabled = `vector-feature-${ name }-${ suffixDisabled }`,
// If neither of the classes can be found it is a legacy feature
isLoggedInOnlyFeature = !classList.contains( featureClassDisabled ) &&
!classList.contains( featureClassEnabled );
// Check in legacy mode.
if ( isLoggedInOnlyFeature && !isNotClientPreference ) {
// try again using the legacy classes
return toggleDocClasses( name, override, true );
} else if ( classList.contains( featureClassDisabled ) || override === true ) {
classList.remove( featureClassDisabled );
classList.add( featureClassEnabled );
return true;
} else if ( classList.contains( featureClassEnabled ) || override === false ) {
classList.add( featureClassDisabled );
classList.remove( featureClassEnabled );
return false;
} else {
throw new Error( `Attempt to toggle unknown feature: ${ name }` );
}
}
/**
* @param {string} name
* @throws {Error} if unknown feature toggled.
*/
function toggle( name ) {
const featureState = toggleDocClasses( name );
save( name, featureState );
}
/**
* Checks if the feature is enabled.
*
* @param {string} name
* @return {boolean}
*/
function isEnabled( name ) {
return document.documentElement.classList.contains( getClass( name, true ) ) ||
document.documentElement.classList.contains( getClass( name, true, true ) );
}
/**
* Get name of feature class.
*
* @param {string} name
* @param {boolean} featureEnabled
* @param {boolean} [isClientPreference] whether the feature is also a client preference
* @return {string}
*/
function getClass( name, featureEnabled, isClientPreference ) {
if ( featureEnabled ) {
const suffix = isClientPreference ? 'clientpref-1' : 'enabled';
return `vector-feature-${ name }-${ suffix }`;
} else {
const suffix = isClientPreference ? 'clientpref-0' : 'disabled';
return `vector-feature-${ name }-${ suffix }`;
}
}
module.exports = { getClass, isEnabled, toggle, toggleDocClasses };