mediawiki-skins-Vector/resources/skins.vector.js/skin.js
Jdrewniak 9b93a64fdf Follow-up to f115016 - Add beta tag & feedback link to Appearance menu
Addresses edge-cases for feedback link for dark-mode.
- Feedback link should not be visible if dark-mode gadget is enabled.
- Feedback link should not be visible if page is excluded from dark mode.

Additionally, turns feedback link green after click
and prevents further clicks on link (without removing link,
since removing the link changes the margins on the text)
and adds heart icon beside success message.

Bug: T367871
Change-Id: Idff14ffa7e8f497ec38250cf10252e998c234057
2024-07-03 18:40:39 -04:00

162 lines
6 KiB
JavaScript

const languageButton = require( './languageButton.js' ),
limitedWidthToggle = require( './limitedWidthToggle.js' ),
pinnableElement = require( './pinnableElement.js' ),
searchToggle = require( './searchToggle.js' ),
echo = require( './echo.js' ),
initExperiment = require( './AB.js' ),
ABTestConfig = require( /** @type {string} */ ( './activeABTest.json' ) ),
initSearchLoader = require( './searchLoader.js' ).initSearchLoader,
portletsManager = require( './portlets.js' ),
dropdownMenus = require( './dropdownMenus.js' ).dropdownMenus,
tables = require( './tables.js' ).init,
watchstar = require( './watchstar.js' ).init,
setupIntersectionObservers = require( './setupIntersectionObservers.js' ),
menuTabs = require( './menuTabs.js' ),
userPreferences = require( './userPreferences.js' ),
legacyMessageBoxStyles = require( './legacyMessageBoxStyles.js' ),
{ isNightModeGadgetEnabled, disableNightModeForGadget, alterExclusionMessage, removeBetaNotice } = require( './disableNightModeIfGadget.js' ),
teleportTarget = /** @type {HTMLElement} */require( /** @type {string} */ ( 'mediawiki.page.ready' ) ).teleportTarget;
/**
* Wait for first paint before calling this function. That's its whole purpose.
*
* Some CSS animations and transitions are "disabled" by default as a workaround to this old Chrome
* bug, https://bugs.chromium.org/p/chromium/issues/detail?id=332189, which otherwise causes them to
* render in their terminal state on page load. By adding the `vector-animations-ready` class to the
* `html` root element **after** first paint, the animation selectors suddenly match causing the
* animations to become "enabled" when they will work properly. A similar pattern is used in Minerva
* (see T234570#5779890, T246419).
*
* Example usage in Less:
*
* ```less
* .foo {
* color: #f00;
* transform: translateX( -100% );
* }
*
* // This transition will be disabled initially for JavaScript users. It will never be enabled for
* // non-JavaScript users.
* .vector-animations-ready .foo {
* transition: transform 100ms ease-out;
* }
* ```
*
* @param {Document} document
* @return {void}
*/
function enableCssAnimations( document ) {
document.documentElement.classList.add( 'vector-animations-ready' );
}
/**
* @param {Window} window
* @return {void}
*/
function main( window ) {
enableCssAnimations( window.document );
initSearchLoader( document );
languageButton();
echo();
portletsManager.main();
watchstar();
limitedWidthToggle();
// Initialize the search toggle for the main header only. The sticky header
// toggle is initialized after Codex search loads.
const searchToggleElement = document.querySelector( '.mw-header .search-toggle' );
if ( searchToggleElement ) {
searchToggle( searchToggleElement );
}
pinnableElement.initPinnableElement();
// Initializes the TOC and sticky header, behaviour of which depend on scroll behaviour.
setupIntersectionObservers.main();
// Apply body styles to teleported elements
teleportTarget.classList.add( 'vector-body' );
// Load client preferences
const appearanceMenuSelector = '#vector-appearance';
const appearanceMenuExists = document.querySelectorAll( appearanceMenuSelector ).length > 0;
if ( appearanceMenuExists ) {
mw.loader.using( [
'skins.vector.clientPreferences',
'skins.vector.search.codex.styles',
'skins.vector.search.codex.scripts'
] ).then( () => {
const clientPreferences = require( /** @type {string} */ ( 'skins.vector.clientPreferences' ) );
const clientPreferenceConfig = ( require( './clientPreferences.json' ) );
// Can be removed once wgVectorNightMode is removed.
if ( document.documentElement.classList.contains( 'vector-feature-night-mode-disabled' ) ) {
// @ts-ignore issues relating to delete operator are not relevant here.
delete clientPreferenceConfig[ 'skin-theme' ];
}
// while we're in beta, temporarily check if the night mode gadget is installed and
// disable our night mode if so
if ( isNightModeGadgetEnabled() ) {
disableNightModeForGadget();
clientPreferences.render( appearanceMenuSelector, clientPreferenceConfig, userPreferences );
alterExclusionMessage();
removeBetaNotice();
} else {
clientPreferences.render( appearanceMenuSelector, clientPreferenceConfig, userPreferences );
}
} );
}
dropdownMenus();
// menuTabs should follow `dropdownMenus` as that can move menu items from a
// tab menu to a dropdown.
menuTabs();
tables();
}
/**
* @param {Window} window
* @return {void}
*/
function init( window ) {
const now = mw.now();
legacyMessageBoxStyles();
// This is the earliest time we can run JS for users (and bucket anonymous
// users for A/B tests).
// Where the browser supports it, for a 10% sample of users
// we record a value to give us a sense of the expected delay in running A/B tests or
// disabling JS features. This will inform us on various things including what to expect
// with regards to delay while running A/B tests to anonymous users.
// When EventLogging is not available this will reject.
// This code can be removed by the end of the Desktop improvements project.
// https://www.mediawiki.org/wiki/Desktop_improvements
mw.loader.using( 'ext.eventLogging' ).then( () => {
if (
mw.eventLog &&
mw.eventLog.eventInSample( 100 /* 1 in 100 */ ) &&
window.performance &&
window.performance.timing &&
window.performance.timing.navigationStart
) {
mw.track( 'timing.Vector.ready', now - window.performance.timing.navigationStart ); // milliseconds
}
} );
}
init( window );
if ( ABTestConfig.enabled && !mw.user.isAnon() ) {
initExperiment( ABTestConfig, String( mw.user.getId() ) );
}
if ( document.readyState === 'interactive' || document.readyState === 'complete' ) {
main( window );
} else {
// This is needed when document.readyState === 'loading'.
document.addEventListener( 'DOMContentLoaded', () => {
main( window );
} );
}
// Provider of skins.vector.js module:
/**
* skins.vector.js
*
* @stable for use inside WikimediaEvents ONLY.
*/
module.exports = { pinnableElement };