2023-11-07 16:29:17 +00:00
|
|
|
( function ( track ) {
|
2024-03-24 20:53:43 +00:00
|
|
|
const MAX_PRINT_TIMEOUT = 3000;
|
|
|
|
let printSetTimeoutReference = 0;
|
|
|
|
const mobile = require( 'mobile.startup' );
|
2023-11-07 16:29:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper function to detect iOs
|
|
|
|
*
|
|
|
|
* @ignore
|
|
|
|
* @param {string} userAgent User Agent
|
|
|
|
* @return {boolean}
|
|
|
|
*/
|
|
|
|
function isIos( userAgent ) {
|
|
|
|
return /ipad|iphone|ipod/i.test( userAgent );
|
|
|
|
}
|
2018-11-08 00:06:54 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper function to retrieve the Android version
|
2020-06-02 21:21:44 +00:00
|
|
|
*
|
2018-11-08 00:06:54 +00:00
|
|
|
* @ignore
|
|
|
|
* @param {string} userAgent User Agent
|
2023-10-19 14:07:38 +00:00
|
|
|
* @return {number|boolean} Integer version number, or false if not found
|
2018-11-08 00:06:54 +00:00
|
|
|
*/
|
|
|
|
function getAndroidVersion( userAgent ) {
|
2024-03-24 20:53:43 +00:00
|
|
|
const match = userAgent.toLowerCase().match( /android\s(\d\.]*)/ );
|
2018-11-27 12:29:39 +00:00
|
|
|
return match ? parseInt( match[ 1 ] ) : false;
|
2018-11-08 00:06:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper function to retrieve the Chrome/Chromium version
|
2020-06-02 21:21:44 +00:00
|
|
|
*
|
2018-11-08 00:06:54 +00:00
|
|
|
* @ignore
|
|
|
|
* @param {string} userAgent User Agent
|
2023-10-19 14:07:38 +00:00
|
|
|
* @return {number|boolean} Integer version number, or false if not found
|
2018-11-08 00:06:54 +00:00
|
|
|
*/
|
|
|
|
function getChromeVersion( userAgent ) {
|
2024-03-24 20:53:43 +00:00
|
|
|
const match = userAgent.toLowerCase().match( /chrom(e|ium)\/(\d+)\./ );
|
2018-11-27 12:29:39 +00:00
|
|
|
return match ? parseInt( match[ 2 ] ) : false;
|
2018-11-08 00:06:54 +00:00
|
|
|
}
|
|
|
|
|
2018-12-20 22:02:57 +00:00
|
|
|
/**
|
|
|
|
* Checks whether DownloadIcon is available for given user agent
|
|
|
|
*
|
|
|
|
* @memberof DownloadIcon
|
|
|
|
* @instance
|
|
|
|
* @param {Window} windowObj
|
|
|
|
* @param {Page} page to download
|
|
|
|
* @param {string} userAgent User agent
|
|
|
|
* @param {number[]} supportedNamespaces where printing is possible
|
|
|
|
* @return {boolean}
|
2020-06-02 21:21:44 +00:00
|
|
|
*/
|
2018-12-20 22:02:57 +00:00
|
|
|
function isAvailable( windowObj, page, userAgent, supportedNamespaces ) {
|
2024-03-24 20:53:43 +00:00
|
|
|
const androidVersion = getAndroidVersion( userAgent );
|
|
|
|
const chromeVersion = getChromeVersion( userAgent );
|
2018-11-08 00:06:54 +00:00
|
|
|
|
2023-01-24 18:06:33 +00:00
|
|
|
if ( typeof window.print !== 'function' ) {
|
|
|
|
// T309591: No window.print support
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-12-20 22:02:57 +00:00
|
|
|
// Download button is restricted to certain namespaces T181152.
|
2019-07-31 23:17:20 +00:00
|
|
|
// Not shown on missing pages
|
2018-12-20 22:02:57 +00:00
|
|
|
// Defaults to 0, in case cached JS has been served.
|
|
|
|
if ( supportedNamespaces.indexOf( page.getNamespaceId() ) === -1 ||
|
2019-07-31 23:17:20 +00:00
|
|
|
page.isMainPage() || page.isMissing ) {
|
2018-12-20 22:02:57 +00:00
|
|
|
// namespace is not supported or it's a main page
|
|
|
|
return false;
|
|
|
|
}
|
2018-11-08 00:06:54 +00:00
|
|
|
|
2023-11-07 16:29:17 +00:00
|
|
|
if ( isIos( userAgent ) || chromeVersion === false ||
|
2018-12-20 22:02:57 +00:00
|
|
|
windowObj.chrome === undefined
|
|
|
|
) {
|
|
|
|
// we support only chrome/chromium on desktop/android
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if ( ( androidVersion && androidVersion < 5 ) || chromeVersion < 41 ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* onClick handler for button that invokes print function
|
2020-06-02 21:21:44 +00:00
|
|
|
*
|
2021-09-27 17:02:06 +00:00
|
|
|
* @param {HTMLElement} portletItem
|
2018-12-20 22:02:57 +00:00
|
|
|
* @param {Icon} spinner
|
2024-01-24 22:02:12 +00:00
|
|
|
* @param {Function} [loadAllImagesInPage]
|
2018-12-20 22:02:57 +00:00
|
|
|
*/
|
2023-11-07 16:29:17 +00:00
|
|
|
function onClick( portletItem, spinner, loadAllImagesInPage ) {
|
2024-03-24 20:53:43 +00:00
|
|
|
const icon = portletItem.querySelector( '.minerva-icon--download' );
|
2018-12-20 22:02:57 +00:00
|
|
|
function doPrint() {
|
2021-09-28 17:00:45 +00:00
|
|
|
printSetTimeoutReference = clearTimeout( printSetTimeoutReference );
|
2018-12-20 22:02:57 +00:00
|
|
|
track( 'minerva.downloadAsPDF', {
|
|
|
|
action: 'callPrint'
|
|
|
|
} );
|
|
|
|
window.print();
|
2021-09-27 17:02:06 +00:00
|
|
|
$( icon ).show();
|
2018-12-20 22:02:57 +00:00
|
|
|
spinner.$el.hide();
|
|
|
|
}
|
2018-11-08 00:06:54 +00:00
|
|
|
|
2018-12-20 22:02:57 +00:00
|
|
|
function doPrintBeforeTimeout() {
|
2021-09-28 17:00:45 +00:00
|
|
|
if ( printSetTimeoutReference ) {
|
2018-12-20 22:02:57 +00:00
|
|
|
doPrint();
|
2018-11-08 00:06:54 +00:00
|
|
|
}
|
|
|
|
}
|
2018-12-20 22:02:57 +00:00
|
|
|
// The click handler may be invoked multiple times so if a pending print is occurring
|
|
|
|
// do nothing.
|
2021-09-28 17:00:45 +00:00
|
|
|
if ( !printSetTimeoutReference ) {
|
2018-12-20 22:02:57 +00:00
|
|
|
track( 'minerva.downloadAsPDF', {
|
|
|
|
action: 'fetchImages'
|
|
|
|
} );
|
2021-09-27 17:02:06 +00:00
|
|
|
$( icon ).hide();
|
2018-12-20 22:02:57 +00:00
|
|
|
spinner.$el.show();
|
|
|
|
// If all image downloads are taking longer to load then the MAX_PRINT_TIMEOUT
|
|
|
|
// abort the spinner and print regardless.
|
2021-09-28 17:00:45 +00:00
|
|
|
printSetTimeoutReference = setTimeout( doPrint, MAX_PRINT_TIMEOUT );
|
2024-03-24 18:49:09 +00:00
|
|
|
( loadAllImagesInPage || mobile.loadAllImagesInPage )()
|
|
|
|
.then( doPrintBeforeTimeout, doPrintBeforeTimeout );
|
2018-12-20 22:02:57 +00:00
|
|
|
}
|
|
|
|
}
|
2018-11-08 00:06:54 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate a download icon for triggering print functionality if
|
2021-09-28 17:00:45 +00:00
|
|
|
* printing is available.
|
|
|
|
* Calling this method has side effects:
|
|
|
|
* It calls mw.util.addPortletLink and may inject an element into the page.
|
2018-11-08 00:06:54 +00:00
|
|
|
*
|
2019-07-31 23:17:20 +00:00
|
|
|
* @param {Page} page
|
2018-11-08 00:06:54 +00:00
|
|
|
* @param {number[]} supportedNamespaces
|
|
|
|
* @param {Window} [windowObj] window object
|
2021-09-27 17:02:06 +00:00
|
|
|
* @param {boolean} [overflowList] Append to overflow list
|
2023-10-19 14:07:38 +00:00
|
|
|
* @return {jQuery|null}
|
2018-11-08 00:06:54 +00:00
|
|
|
*/
|
2021-09-27 17:02:06 +00:00
|
|
|
function downloadPageAction( page, supportedNamespaces, windowObj, overflowList ) {
|
2024-03-24 20:53:43 +00:00
|
|
|
const spinner = ( overflowList ) ? mobile.spinner( {
|
|
|
|
label: '',
|
|
|
|
isIconOnly: false
|
|
|
|
} ) : mobile.spinner();
|
2019-04-10 20:31:14 +00:00
|
|
|
|
2018-11-08 00:06:54 +00:00
|
|
|
if (
|
2018-12-20 22:02:57 +00:00
|
|
|
isAvailable(
|
2019-07-31 23:17:20 +00:00
|
|
|
windowObj, page, navigator.userAgent,
|
2018-11-08 00:06:54 +00:00
|
|
|
supportedNamespaces
|
|
|
|
)
|
|
|
|
) {
|
2023-09-27 00:17:21 +00:00
|
|
|
// FIXME: Use p-views when cache has cleared.
|
|
|
|
const actionID = document.querySelector( '#p-views' ) ? 'p-views' : 'page-actions';
|
2024-03-24 20:53:43 +00:00
|
|
|
const portletLink = mw.util.addPortletLink(
|
2023-09-27 00:17:21 +00:00
|
|
|
overflowList ? 'page-actions-overflow' : actionID,
|
2021-09-27 17:02:06 +00:00
|
|
|
'#',
|
2022-08-26 08:40:48 +00:00
|
|
|
mw.msg( 'minerva-download' ),
|
2021-09-27 17:02:06 +00:00
|
|
|
// id
|
|
|
|
'minerva-download',
|
|
|
|
// tooltip
|
2022-08-26 08:40:48 +00:00
|
|
|
mw.msg( 'minerva-download' ),
|
2021-09-27 17:02:06 +00:00
|
|
|
// access key
|
|
|
|
'p',
|
|
|
|
overflowList ? null : document.getElementById( 'page-actions-watch' )
|
|
|
|
);
|
|
|
|
if ( portletLink ) {
|
2024-06-03 12:06:43 +00:00
|
|
|
portletLink.addEventListener( 'click', () => {
|
2023-11-07 16:29:17 +00:00
|
|
|
onClick( portletLink, spinner, mobile.loadAllImagesInPage );
|
2021-09-28 17:00:45 +00:00
|
|
|
} );
|
2024-03-24 20:53:43 +00:00
|
|
|
const iconElement = portletLink.querySelector( '.minerva-icon' );
|
2021-09-27 17:02:06 +00:00
|
|
|
if ( iconElement ) {
|
2023-09-05 17:07:13 +00:00
|
|
|
iconElement.classList.add( 'minerva-icon--download' );
|
2021-09-27 17:02:06 +00:00
|
|
|
}
|
2023-07-27 03:33:21 +00:00
|
|
|
spinner.$el.hide().insertBefore(
|
2023-08-09 21:49:19 +00:00
|
|
|
$( portletLink ).find( '.minerva-icon' )
|
2023-07-27 03:33:21 +00:00
|
|
|
);
|
2021-09-27 17:02:06 +00:00
|
|
|
}
|
|
|
|
return portletLink;
|
2018-11-08 00:06:54 +00:00
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-02 21:10:10 +00:00
|
|
|
module.exports = {
|
2023-11-07 16:29:17 +00:00
|
|
|
downloadPageAction,
|
2019-07-02 21:10:10 +00:00
|
|
|
test: {
|
2023-11-07 16:29:17 +00:00
|
|
|
isAvailable,
|
|
|
|
onClick
|
2019-07-02 21:10:10 +00:00
|
|
|
}
|
|
|
|
};
|
2019-09-27 18:53:01 +00:00
|
|
|
|
2023-11-07 16:29:17 +00:00
|
|
|
}( mw.track ) );
|