Limited width uses new client preferences system

* Update classes to use clientpref-1 and clientpref-0 suffix for limited width
I've limited this to the only client preference for now to reduce
risk.
* For cached HTML retain existing CSS rules, and continue saving
a cookie
* Migrate cookie if found for newly generated pages. This will be
to ensure the old cookie and new cookie are in sync (this should be
a one time operation)

Depends-On: I1e635f843ac9b2f248b1f7618134598e80291b38
Bug: T341641
Change-Id: I120f8f7114b33d2cfbd1c3c57ebf41f8b2d7fec4
This commit is contained in:
Jon Robson 2023-07-11 16:13:57 -07:00 committed by Jdlrobson
parent 9444cfe58c
commit e5bf8adad7
9 changed files with 89 additions and 10 deletions

View file

@ -137,8 +137,22 @@ class FeatureManager {
return array_map( static function ( $featureName ) use ( $featureManager ) {
// switch to lower case and switch from camel case to hyphens
$featureClass = ltrim( strtolower( preg_replace( '/[A-Z]([A-Z](?![a-z]))*/', '-$0', $featureName ) ), '-' );
// Client side preferences
switch ( $featureClass ) {
case 'limited-width':
$suffixEnabled = 'clientpref-1';
$suffixDisabled = 'clientpref-0';
break;
default:
// FIXME: Eventually this should not be necessary.
$suffixEnabled = 'enabled';
$suffixDisabled = 'disabled';
break;
}
$prefix = 'vector-feature-' . $featureClass . '-';
return $featureManager->isFeatureEnabled( $featureName ) ? $prefix . 'enabled' : $prefix . 'disabled';
return $featureManager->isFeatureEnabled( $featureName ) ?
$prefix . $suffixEnabled : $prefix . $suffixDisabled;
}, array_keys( $this->features ) );
}

View file

@ -13,11 +13,20 @@ function save( feature, enabled ) {
if ( !mw.user.isNamed() ) {
switch ( feature ) {
case 'limited-width':
// FIXME: Cookie is set for cached HTML using the older inline script.
// When removing this code,
// please retain `mw.cookie.set( 'mwclientprefs', null );` for 1-4 weeks
// to clean up after ourselves so users don't have a non-expiring cookie which
// serves no purpose.
if ( enabled ) {
mw.cookie.set( 'mwclientprefs', null );
} else {
mw.cookie.set( 'mwclientprefs', 'vector-feature-limited-width' );
}
// Save the setting under the new system
// @ts-ignore https://github.com/wikimedia/typescript-types/pull/44
mw.user.clientPrefs.set( `vector-feature-${feature}`, enabled ? '1' : '0' );
break;
default:
// not a supported anonymous preference
@ -35,14 +44,18 @@ function save( feature, enabled ) {
*
* @param {string} name feature name
* @param {boolean} [override] option to force enabled or disabled state.
*
* @param {boolean} [isLegacy] should we search for legacy classes
* FIXME: this is for supporting cached HTML,
* this should be removed 1-4 weeks after the patch has been in production.
* @return {boolean} The new feature state (false=disabled, true=enabled).
* @throws {Error} if unknown feature toggled.
*/
function toggleDocClasses( name, override ) {
const featureClassEnabled = `vector-feature-${name}-enabled`,
function toggleDocClasses( name, override, isLegacy ) {
const suffixEnabled = isLegacy ? 'enabled' : 'clientpref-1';
const suffixDisabled = isLegacy ? 'disabled' : 'clientpref-0';
const featureClassEnabled = `vector-feature-${name}-${suffixEnabled}`,
classList = document.documentElement.classList,
featureClassDisabled = `vector-feature-${name}-disabled`;
featureClassDisabled = `vector-feature-${name}-${suffixDisabled}`;
if ( classList.contains( featureClassDisabled ) || override === true ) {
classList.remove( featureClassDisabled );
@ -52,6 +65,9 @@ function toggleDocClasses( name, override ) {
classList.add( featureClassDisabled );
classList.remove( featureClassEnabled );
return false;
} else if ( !isLegacy ) {
// try again using the legacy classes
return toggleDocClasses( name, override, true );
} else {
throw new Error( `Attempt to toggle unknown feature: ${name}` );
}
@ -73,7 +89,8 @@ function toggle( name ) {
* @return {boolean}
*/
function isEnabled( name ) {
return document.documentElement.classList.contains( getClass( name, true ) );
return document.documentElement.classList.contains( getClass( name, true ) ) ||
document.documentElement.classList.contains( getClass( name, true, true ) );
}
/**
@ -81,13 +98,17 @@ function isEnabled( name ) {
*
* @param {string} name
* @param {boolean} featureEnabled
* @param {boolean} [isLegacy] FIXME: this is for supporting cached HTML,
* this should be removed 1-4 weeks after the patch has been in production.
* @return {string}
*/
function getClass( name, featureEnabled ) {
function getClass( name, featureEnabled, isLegacy ) {
if ( featureEnabled ) {
return `vector-feature-${name}-enabled`;
const suffix = isLegacy ? 'enabled' : '1';
return `vector-feature-${name}-${suffix}`;
} else {
return `vector-feature-${name}-disabled`;
const suffix = isLegacy ? 'disabled' : '0';
return `vector-feature-${name}-${suffix}`;
}
}

View file

@ -34,6 +34,34 @@ function init() {
const settings = /** @type {HTMLElement|null} */ ( document.querySelector( '.vector-settings' ) );
const toggle = /** @type {HTMLElement|null} */ ( document.querySelector( '.vector-limited-width-toggle' ) );
const toggleIcon = /** @type {HTMLElement|null} */ ( document.querySelector( '.vector-limited-width-toggle .vector-icon' ) );
const cookie = mw.cookie.get( 'mwclientprefs' );
// @ts-ignore https://github.com/wikimedia/typescript-types/pull/42
const existingValue = mw.user.clientPrefs.get( 'vector-feature-limited-width' );
// On a cached page existingValue will return false.
// If the cookie is set then we need to add the appropriate class to the page
// so that the toggle works correctly.
if ( !existingValue ) {
document.documentElement.classList.add(
`vector-feature-limited-width-clientpref-${cookie ? '0' : '1'}`
);
document.documentElement.classList.remove(
'vector-feature-limited-width-disabled',
'vector-feature-limited-width-enabled'
);
}
// Sync cookie value with clientPrefs if the two are misaligned.
if ( cookie && existingValue === '1' ) {
// @ts-ignore https://github.com/wikimedia/typescript-types/pull/42
mw.user.clientPrefs.set( 'vector-feature-limited-width', '0' );
// Update the display.
document.documentElement.classList.remove(
'vector-feature-limited-width-clientpref-1',
'vector-feature-limited-width-enabled'
);
document.documentElement.classList.add(
'vector-feature-limited-width-clientpref-0'
);
}
if ( !settings || !toggle || !toggleIcon ) {
return;

View file

@ -60,7 +60,9 @@
}
}
}
// FIXME: Remove -disabled when cache has cleared.
&.vector-feature-limited-width-clientpref-0 .mw-content-container,
&.vector-feature-limited-width-clientpref-0 .mw-table-of-contents-container,
&.vector-feature-limited-width-disabled .mw-content-container,
&.vector-feature-limited-width-content-disabled .mw-content-container,
&.vector-feature-limited-width-disabled .mw-table-of-contents-container,
@ -122,6 +124,8 @@
column-gap: @grid-column-gap;
}
// FIXME: Remove -disabled when cache has cleared.
&.vector-feature-limited-width-clientpref-0 .mw-body,
&.vector-feature-limited-width-disabled .mw-body,
&.vector-feature-limited-width-content-disabled .mw-body {
grid-template-columns: ~'minmax(0, 1fr) min-content';

View file

@ -4,6 +4,8 @@
.mixin-page-container();
}
// FIXME: Remove -disabled when cache has cleared.
&.vector-feature-limited-width-clientpref-0 .vector-header-container,
&.vector-feature-limited-width-disabled .vector-header-container {
max-width: none;
}

View file

@ -129,6 +129,8 @@ body {
}
}
// FIXME: Remove -disabled when cache has cleared.
&.vector-feature-limited-width-clientpref-0 .mw-page-container,
&.vector-feature-limited-width-disabled .mw-page-container {
max-width: none;
}

View file

@ -115,6 +115,8 @@
column-gap: @grid-column-gap;
}
// FIXME: Remove -disabled when cache has cleared.
&.vector-feature-limited-width-clientpref-0 .mw-body,
&.vector-feature-limited-width-disabled .mw-body,
&.vector-feature-limited-width-content-disabled .mw-body {
grid-template-columns: ~'minmax(0, 1fr) min-content';

View file

@ -183,6 +183,10 @@ body {
.mixin-vector-page-container-sizing();
}
// FIXME: Remove -disabled when cache has cleared.
&.vector-feature-limited-width-clientpref-0 .mw-page-container,
&.vector-feature-limited-width-clientpref-0 .vector-sticky-header,
&.vector-feature-limited-width-clientpref-0 .mw-header,
&.vector-feature-limited-width-disabled .mw-page-container,
&.vector-feature-limited-width-disabled .vector-sticky-header,
&.vector-feature-limited-width-disabled .mw-header {

View file

@ -1,5 +1,7 @@
@import '../resources/common/variables.less';
// FIXME: Remove -enabled when cache has cleared.
.vector-feature-limited-width-clientpref-1 #wikiPreview,
.vector-feature-limited-width-enabled #wikiPreview {
// @max-width-content-container is defined in ems, so the final width depends on font-size,
// but this element is nested in an element with a different font-size. Divide by the