-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(preferences): ✨ implement a localStorage version of mw.user.clie…
…ntPrefs This is the first step of migrating to the clientPrefs library when it is avaliable. Currently only themes are using it and the standard classes are added to the HTML element. Related: #780
- Loading branch information
1 parent
59aa0a9
commit ed226a4
Showing
3 changed files
with
135 additions
and
1 deletion.
There are no files selected for viewing
116 changes: 116 additions & 0 deletions
116
resources/skins.citizen.preferences/clientPrefs.localStorage.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/** | ||
* mw.user.clientPrefs modified to only use localStorage | ||
* TODO: Revisit when we move to MW 1.43 and the interface is more stable | ||
*/ | ||
|
||
const CLIENTPREF_STORAGE_NAME = 'mwclientpreferences'; | ||
const CLIENTPREF_SUFFIX = '-clientpref-'; | ||
const CLIENTPREF_DELIMITER = ','; | ||
|
||
/** | ||
* Check if the feature name is composed of valid characters. | ||
* | ||
* A valid feature name may contain letters, numbers, and "-" characters. | ||
* | ||
* @private | ||
* @param {string} value | ||
* @return {boolean} | ||
*/ | ||
function isValidFeatureName( value ) { | ||
return value.match( /^[a-zA-Z0-9-]+$/ ) !== null; | ||
} | ||
|
||
/** | ||
* Check if the value is composed of valid characters. | ||
* | ||
* @private | ||
* @param {string} value | ||
* @return {boolean} | ||
*/ | ||
function isValidFeatureValue( value ) { | ||
return value.match( /^[a-zA-Z0-9]+$/ ) !== null; | ||
} | ||
|
||
/** | ||
* Save the feature value to the client preferences localStorage. | ||
* Modified from the original to use localStorage instead of cookie. | ||
* | ||
* @private | ||
* @param {string} feature | ||
* @param {string} value | ||
*/ | ||
function saveClientPrefs( feature, value ) { | ||
const existingStorage = mw.storage.get( CLIENTPREF_STORAGE_NAME ) || ''; | ||
const data = {}; | ||
existingStorage.split( CLIENTPREF_DELIMITER ).forEach( function ( keyValuePair ) { | ||
const m = keyValuePair.match( /^([\w-]+)-clientpref-(\w+)$/ ); | ||
if ( m ) { | ||
data[ m[ 1 ] ] = m[ 2 ]; | ||
} | ||
} ); | ||
data[ feature ] = value; | ||
|
||
const newStorage = Object.keys( data ).map( function ( key ) { | ||
return key + CLIENTPREF_SUFFIX + data[ key ]; | ||
} ).join( CLIENTPREF_DELIMITER ); | ||
mw.storage.set( CLIENTPREF_STORAGE_NAME, newStorage ); | ||
} | ||
|
||
function clientPrefs() { | ||
return { | ||
/** | ||
* Change the class on the HTML document element, and save the value in a localStorage. | ||
* | ||
* @memberof mw.user.clientPrefs | ||
* @param {string} feature | ||
* @param {string} value | ||
* @return {boolean} True if feature was stored successfully, false if the value | ||
* uses a forbidden character or the feature is not recognised | ||
* e.g. a matching class was not defined on the HTML document element. | ||
*/ | ||
set: function ( feature, value ) { | ||
if ( !isValidFeatureName( feature ) || !isValidFeatureValue( value ) ) { | ||
return false; | ||
} | ||
const currentValue = this.get( feature ); | ||
|
||
const oldFeatureClass = feature + CLIENTPREF_SUFFIX + currentValue; | ||
const newFeatureClass = feature + CLIENTPREF_SUFFIX + value; | ||
// The following classes are removed here: | ||
// * feature-name-clientpref-<old-feature-value> | ||
// * e.g. vector-font-size--clientpref-small | ||
document.documentElement.classList.remove( oldFeatureClass ); | ||
// The following classes are added here: | ||
// * feature-name-clientpref-<feature-value> | ||
// * e.g. vector-font-size--clientpref-xlarge | ||
document.documentElement.classList.add( newFeatureClass ); | ||
saveClientPrefs( feature, value ); | ||
return true; | ||
}, | ||
|
||
/** | ||
* Retrieve the current value of the feature from the HTML document element. | ||
* | ||
* @memberof mw.user.clientPrefs | ||
* @param {string} feature | ||
* @return {string|boolean} returns boolean if the feature is not recognized | ||
* returns string if a feature was found. | ||
*/ | ||
get: function ( feature ) { | ||
const featurePrefix = feature + CLIENTPREF_SUFFIX; | ||
const docClass = document.documentElement.className; | ||
// eslint-disable-next-line security/detect-non-literal-regexp | ||
const featureRegEx = new RegExp( | ||
'(^| )' + mw.util.escapeRegExp( featurePrefix ) + '([a-zA-Z0-9]+)( |$)' | ||
); | ||
const match = docClass.match( featureRegEx ); | ||
|
||
// check no further matches if we replaced this occurance. | ||
const isAmbiguous = docClass.replace( featureRegEx, '$1$3' ).match( featureRegEx ) !== null; | ||
return !isAmbiguous && match ? match[ 2 ] : false; | ||
} | ||
}; | ||
} | ||
|
||
/** @module clientPrefs */ | ||
module.exports = clientPrefs; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters