wikimedia/mediawiki-extensions-MobileFrontend

View on GitHub
src/mobile.startup/time.js

Summary

Maintainability
A
1 hr
Test Coverage
const units = [ 'seconds', 'minutes', 'hours', 'days', 'months', 'years' ],
    util = require( './util' ),
    limits = [ 1, 60, 3600, 86400, 2592000, 31536000 ];

/**
 * Calculate the correct unit of timestamp
 *
 * @memberof module:mobile.startup/time
 * @instance
 * @param {number} timestampDelta
 * @return {{value: number, unit: string}}
 */
function timeAgo( timestampDelta ) {
    let i = 0;
    while ( i < limits.length && timestampDelta > limits[i + 1] ) {
        ++i;
    }
    return {
        value: Math.round( timestampDelta / limits[i] ),
        unit: units[i]
    };
}

/**
 * Calculate the correct unit of timestamp delta
 *
 * @memberof module:mobile.startup/time
 * @param {number} timestamp
 * @return {{value: number, unit: string}}
 */
function getTimeAgoDelta( timestamp ) {
    const currentTimestamp = Math.round( Date.now() / 1000 );

    return timeAgo( currentTimestamp - timestamp );
}

/**
 * Whether timestamp delta is less than a day old
 *
 * @instance
 * @memberof module:mobile.startup/time
 * @param {{value: number, unit: string}} delta Object of timestamp and its label
 * @return {boolean}
 */
function isRecent( delta ) {
    return [ 'seconds', 'minutes', 'hours' ].indexOf( delta.unit ) > -1;
}

/**
 * Is delta less than 10 seconds?
 *
 * @instance
 * @memberof module:mobile.startup/time
 * @param {{value: number, unit: string}} delta Object of timestamp and its label
 * @return {boolean}
 */
function isNow( delta ) {
    return delta.unit === 'seconds' && delta.value < 10;
}

/**
 * Return a message relating to the last modified relative time.
 *
 * @instance
 * @memberof module:mobile.startup/time
 * @param {number} ts timestamp
 * @param {string} username of the last user to modify the page
 * @param {string} gender of the last user to modify the page
 * @param {string} historyUrl url to the history page for the message (deprecated)
 * @return {string}
 */
function getLastModifiedMessage( ts, username, gender, historyUrl ) {
    const linkAll = typeof historyUrl === 'undefined',
        keys = {
            seconds: 'mobile-frontend-last-modified-with-user-seconds',
            minutes: 'mobile-frontend-last-modified-with-user-minutes',
            hours: 'mobile-frontend-last-modified-with-user-hours',
            days: 'mobile-frontend-last-modified-with-user-days',
            months: 'mobile-frontend-last-modified-with-user-months',
            years: 'mobile-frontend-last-modified-with-user-years'
        },
        args = [];

    gender = gender || 'unknown';

    const delta = getTimeAgoDelta( ts );
    if ( isNow( delta ) ) {
        args.push( 'mobile-frontend-last-modified-with-user-just-now', gender, username );
    } else {
        args.push( keys[ delta.unit ], gender, username,
            mw.language.convertNumber( delta.value )
        );
    }

    const lastEditedElement = linkAll ?
        util.parseHTML( '<strong>' ).attr( 'class', 'last-modified-text-accent' ) :
        util.parseHTML( '<a>' ).attr( 'href', historyUrl || '#' );
    const usernameElement = linkAll ?
        util.parseHTML( '<span>' ).attr( 'class', 'last-modified-text-accent' ) :
        util.parseHTML( '<a>' ).attr( 'href', mw.util.getUrl( 'User:' + username ) );

    args.push(
        lastEditedElement,
        // Abuse PLURAL support to determine if the user is anonymous or not
        mw.language.convertNumber( username ? 1 : 0 ),
        // Our abuse of PLURAL support means we have to pass the relative URL
        // rather than construct it from a wikilink
        username ? usernameElement : ''
    );

    return mw.message.apply( this, args ).parse();
}

/**
 * Return a message relating to the registration date of the user
 *
 * @instance
 * @memberof module:mobile.startup/time
 * @param {string} ts timestamp
 * @param {string} [gender] of the last user editing this page
 * @return {string}
 */
function getRegistrationMessage( ts, gender ) {
    const keys = {
        seconds: 'mobile-frontend-joined-seconds',
        minutes: 'mobile-frontend-joined-minutes',
        hours: 'mobile-frontend-joined-hours',
        days: 'mobile-frontend-joined-days',
        months: 'mobile-frontend-joined-months',
        years: 'mobile-frontend-joined-years'
    };

    const args = [];

    gender = gender || 'unknown';

    const delta = getTimeAgoDelta( parseInt( ts, 10 ) );
    if ( isNow( delta ) ) {
        args.push( 'mobile-frontend-joined-just-now', gender );
    } else {
        args.push( keys[ delta.unit ], gender, mw.language.convertNumber( delta.value ) );
    }
    const html = mw.message.apply( this, args ).parse();
    return html;
}

/**
 * Utility library for relative time.
 *
 * @exports module:mobile.startup/time
 */
module.exports = {
    getLastModifiedMessage,
    getRegistrationMessage,
    timeAgo,
    getTimeAgoDelta,
    isNow,
    isRecent
};