Add watchstar to sticky header (alternative)

Bug: T294759
Depends-on: I88af8585e8fc75f77ebef867d267199aeb2c6592
Change-Id: I15c409830ef8970ff7319b4dd447904443949b8d
This commit is contained in:
bwang 2021-11-15 17:09:51 -06:00 committed by jdlrobson
parent 4e8585957e
commit bd799ecc2e
4 changed files with 73 additions and 6 deletions

View file

@ -68,6 +68,16 @@ class SkinVector extends SkinMustache {
'tabindex' => '-1',
'class' => 'sticky-header-icon'
];
// Event and icon will be updated depending on watchstar state
private const WATCHSTAR_ICON = [
'href' => '#',
'id' => 'ca-watchstar-sticky-header',
'event' => 'watch-sticky-header',
'icon' => 'wikimedia-star',
'is-quiet' => true,
'tabindex' => '-1',
'class' => 'sticky-header-icon mw-watchlink'
];
private const EDIT_VE_ICON = [
'href' => '#',
'id' => 'ca-ve-edit-sticky-header',
@ -466,6 +476,7 @@ class SkinVector extends SkinMustache {
$btns = [
self::TALK_ICON,
self::HISTORY_ICON,
self::WATCHSTAR_ICON,
];
if ( $includeEditIcons ) {
$btns[] = self::EDIT_WIKITEXT_ICON;

View file

@ -18,6 +18,7 @@
"wmf": {
"linkMap": {
"\"addEventListener\"": "https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener",
"jQuery": "https://api.jquery.com",
"Document": "https://developer.mozilla.org/docs/Web/API/Document",
"Element": "https://developer.mozilla.org/docs/Web/API/Element",
"Event": "https://developer.mozilla.org/docs/Web/API/Event",

View file

@ -117,18 +117,52 @@ function removeClassFromNodes( nodes, className ) {
} );
}
/**
* Ensures a sticky header button has the correct attributes
*
* @param {HTMLElement} watchSticky
* @param {string} status 'watched', 'unwatched', or 'temporary'
*/
function updateStickyWatchlink( watchSticky, status ) {
/* eslint-disable mediawiki/class-doc */
watchSticky.classList.toggle( 'mw-ui-icon-wikimedia-star', status === 'unwatched' );
watchSticky.classList.toggle( 'mw-ui-icon-wikimedia-unStar', status === 'watched' );
watchSticky.classList.toggle( 'mw-ui-icon-wikimedia-halfStar', status === 'temporary' );
/* eslint-enable mediawiki/class-doc */
watchSticky.setAttribute( 'data-event-name', status === 'unwatched' ? 'watch-sticky-header' : 'unwatch-sticky-header' );
}
/**
* Callback for watchsar
*
* @param {jQuery} $link Watchstar link
* @param {boolean} isWatched The page is watched
* @param {string} [expiry] Optional expiry time
*/
function watchstarCallback( $link, isWatched, expiry ) {
updateStickyWatchlink(
// @ts-ignore
$link[ 0 ],
expiry !== 'infinity' ? 'temporary' :
isWatched ? 'watched' : 'unwatched'
);
}
/**
* Makes sticky header icons functional for modern Vector.
*
* @param {HTMLElement} headerElement
* @param {HTMLElement|null} history
* @param {HTMLElement|null} talk
* @param {HTMLElement|null} watch
*/
function prepareIcons( headerElement, history, talk ) {
function prepareIcons( headerElement, history, talk, watch ) {
const historySticky = headerElement.querySelector( '#ca-history-sticky-header' ),
talkSticky = headerElement.querySelector( '#ca-talk-sticky-header' );
talkSticky = headerElement.querySelector( '#ca-talk-sticky-header' ),
watchSticky = headerElement.querySelector( '#ca-watchstar-sticky-header' );
if ( !historySticky || !talkSticky ) {
if ( !historySticky || !talkSticky || !watchSticky ) {
throw new Error( 'Sticky header has unexpected HTML' );
}
@ -144,6 +178,22 @@ function prepareIcons( headerElement, history, talk ) {
// @ts-ignore
talkSticky.parentNode.removeChild( talkSticky );
}
if ( watch && watch.parentNode instanceof HTMLElement ) {
const watchContainer = watch.parentNode;
copyButtonAttributes( watch, watchSticky );
updateStickyWatchlink(
// @ts-ignore
watchSticky,
watchContainer.classList.contains( 'mw-watchlink-temp' ) ? 'temporary' :
watchContainer.getAttribute( 'id' ) === 'ca-watch' ? 'unwatched' : 'watched'
);
const watchLib = require( /** @type {string} */( 'mediawiki.page.watch.ajax' ) );
watchLib.watchstar( $( watchSticky ), mw.config.get( 'wgRelevantPageName' ), watchstarCallback );
} else {
// @ts-ignore
watchSticky.parentNode.removeChild( watchSticky );
}
}
/**
@ -331,7 +381,8 @@ function makeStickyHeaderFunctional(
prepareIcons( headerElement,
document.querySelector( '#ca-history a' ),
document.querySelector( '#ca-talk a' )
document.querySelector( '#ca-talk a' ),
document.querySelector( '#ca-watch a, #ca-unwatch a' )
);
const veEdit = document.querySelector( '#ca-ve-edit a' );

View file

@ -179,10 +179,13 @@
"class": "ResourceLoaderOOUIIconPackModule",
"variants": [],
"icons": [
"history",
"speechBubbles",
"edit",
"editLock",
"halfStar",
"history",
"speechBubbles",
"star",
"unStar",
"wikiText"
]
},
@ -231,6 +234,7 @@
"dependencies": [
"skins.vector.icons.js",
"mediawiki.page.ready",
"mediawiki.page.watch.ajax",
"mediawiki.util",
"mediawiki.experiments"
]