mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo
synced 2024-11-12 09:26:05 +00:00
eea0dea7ce
We need the API to return the notifications for the special page in timestamp order and not read/unread order, so that the 'continue' value is still correct. On top of that, if we have many unread notifications, they should still be placed according to the dates, so the API must bring back proper result. In this fix, we add 'unreadFirst' to filters, and only use that filter when needed (namely, in the popup) Bug: T136885 Change-Id: I3018d09b009d735402d83074a5ffcd14ea1c242a
255 lines
7.9 KiB
JavaScript
255 lines
7.9 KiB
JavaScript
( function ( mw, $ ) {
|
|
/**
|
|
* Abstract notification API handler
|
|
*
|
|
* @abstract
|
|
* @class
|
|
*
|
|
* @constructor
|
|
* @param {mw.Api} api
|
|
* @param {Object} [config] Configuration object
|
|
* @cfg {number} [limit=25] The limit on how many notifications to fetch
|
|
* @cfg {string} [userLang=mw.config.get( 'wgUserLanguage' )] User language. Defaults
|
|
* to the default user language configuration settings.
|
|
*/
|
|
mw.echo.api.APIHandler = function MwEchoApiAPIHandler( api, config ) {
|
|
config = config || {};
|
|
|
|
this.fetchNotificationsPromise = {};
|
|
this.apiErrorState = {};
|
|
|
|
this.limit = config.limit || 25;
|
|
this.userLang = config.userLang || mw.config.get( 'wgUserLanguage' );
|
|
|
|
this.api = api;
|
|
|
|
// Map the logical type to the type
|
|
// that the API recognizes
|
|
this.normalizedType = {
|
|
message: 'message',
|
|
alert: 'alert',
|
|
all: 'message|alert'
|
|
};
|
|
|
|
// Parameters that are sent through
|
|
// to the 'fetch notification' promise
|
|
// per type
|
|
this.typeParams = {
|
|
message: {},
|
|
alert: {},
|
|
all: {}
|
|
};
|
|
};
|
|
|
|
/* Setup */
|
|
|
|
OO.initClass( mw.echo.api.APIHandler );
|
|
|
|
/**
|
|
* Fetch notifications from the API.
|
|
*
|
|
* @param {string} type Notification type
|
|
* @param {Object} [overrideParams] An object defining parameters to override in the API
|
|
* fetching call.
|
|
* @return {jQuery.Promise} A promise that resolves with an object containing the
|
|
* notification items
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.fetchNotifications = null;
|
|
|
|
/**
|
|
* Fetch all pages with unread notifications in them per wiki
|
|
*
|
|
* @param {string|string[]} [sources=*] Requested sources. If not given
|
|
* or if a '*' is given, all available sources will be queried
|
|
* @return {jQuery.Promise} Promise that is resolved with an object
|
|
* of pages with the number of unread notifications per wiki
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.fetchUnreadNotificationPages = function ( sources ) {
|
|
var params = {
|
|
action: 'query',
|
|
meta: 'unreadnotificationpages'
|
|
};
|
|
|
|
if ( !sources || sources === '*' ) {
|
|
params.unpwikis = '*';
|
|
} else {
|
|
sources = Array.isArray( sources ) ? sources : [ sources ];
|
|
params.unpwikis = sources.join( '|' );
|
|
}
|
|
|
|
return this.api.get( params );
|
|
};
|
|
|
|
/**
|
|
* Check if the given source is local
|
|
*
|
|
* @param {string|string[]} sources Source names
|
|
* @return {boolean} Source is local
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.isSourceLocal = function ( sources ) {
|
|
return Array.isArray( sources ) ?
|
|
(
|
|
sources.indexOf( 'local' ) !== -1 ||
|
|
sources.indexOf( mw.config.get( 'wgDBname' ) ) !== -1
|
|
) :
|
|
(
|
|
sources === 'local' ||
|
|
sources === mw.config.get( 'wgDBname' )
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Create a new fetchNotifications promise that queries the API and overrides
|
|
* the cached promise.
|
|
*
|
|
* @param {string} type Notification type
|
|
* @param {string[]} [sources] An array of sources to query
|
|
* @param {Object} [overrideParams] An object defining parameters to override in the API
|
|
* fetching call.
|
|
* @return {jQuery.Promise} Promise that is resolved when notifications are
|
|
* fetched from the API.
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.createNewFetchNotificationPromise = function ( type, sources, overrideParams ) {
|
|
var apiErrState, fetchNotifPromise,
|
|
fetchingSource = 'local',
|
|
me = this,
|
|
params = $.extend( {
|
|
action: 'query',
|
|
meta: 'notifications',
|
|
notsections: this.normalizedType[ type ],
|
|
notformat: 'model',
|
|
notlimit: this.limit,
|
|
notprop: 'list|count',
|
|
uselang: this.userLang
|
|
}, this.getTypeParams( type ) );
|
|
|
|
if ( !this.isSourceLocal( sources ) ) {
|
|
params.notwikis = sources.join( '|' );
|
|
params.notfilter = '!read';
|
|
fetchingSource = 'foreign';
|
|
}
|
|
|
|
// Initialize the nested value if it doesn't yet exist
|
|
this.fetchNotificationsPromise[ type ] = this.fetchNotificationsPromise[ type ] || {};
|
|
me.apiErrorState[ type ] = me.apiErrorState[ type ] || {};
|
|
|
|
// Reset cached values
|
|
apiErrState = false;
|
|
this.fetchNotificationsPromise[ type ][ fetchingSource ] = null;
|
|
this.apiErrorState[ type ][ fetchingSource ] = false;
|
|
|
|
// Create the fetch promise
|
|
fetchNotifPromise = this.api.get( $.extend( true, params, overrideParams ) );
|
|
|
|
// Only cache promises that don't have override params in them
|
|
if ( !overrideParams ) {
|
|
this.fetchNotificationsPromise[ type ][ fetchingSource ] = fetchNotifPromise;
|
|
}
|
|
|
|
return fetchNotifPromise
|
|
.fail( function () {
|
|
// Mark API error state
|
|
me.apiErrorState[ type ][ fetchingSource ] = true;
|
|
} );
|
|
};
|
|
|
|
/**
|
|
* Update the seen timestamp
|
|
*
|
|
* @param {string} [type] Notification type 'message', 'alert' or 'all'.
|
|
* @return {jQuery.Promise} A promise that resolves with the seen timestamp
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.updateSeenTime = null;
|
|
|
|
/**
|
|
* Mark all notifications as read
|
|
*
|
|
* @param {string|string[]} type Notification type 'message', 'alert' or 'all'.
|
|
* @return {jQuery.Promise} A promise that resolves when all notifications
|
|
* are marked as read.
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.markAllRead = null;
|
|
|
|
/**
|
|
* Mark multiple notification items as read using specific IDs
|
|
*
|
|
* @abstract
|
|
* @param {string[]} itemIdArray An array of notification item IDs
|
|
* @param {boolean} [isRead] Item's new read state; true for marking the item
|
|
* as read, false for marking the item as unread
|
|
* @return {jQuery.Promise} A promise that resolves when all given notifications
|
|
* are marked as read.
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.markItemsRead = null;
|
|
|
|
/**
|
|
* Update the read status of a notification item in the API
|
|
*
|
|
* @param {string} itemId Item id
|
|
* @param {boolean} [isRead] Item's new read state; true for marking the item
|
|
* as read, false for marking the item as unread
|
|
* @return {jQuery.Promise} A promise that resolves when the notifications
|
|
* are marked as read.
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.markItemRead = function ( itemId, isRead ) {
|
|
return this.markItemsRead( [ itemId ], isRead );
|
|
};
|
|
|
|
/**
|
|
* Query the API for unread count of the notifications in this model
|
|
*
|
|
* @param {string} type Notification type 'message', 'alert' or 'all'.
|
|
* @return {jQuery.Promise} jQuery promise that's resolved when the unread count is fetched
|
|
* and the badge label is updated.
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.fetchUnreadCount = null;
|
|
|
|
/**
|
|
* Check whether the model has an API error state flagged
|
|
*
|
|
* @param {string} type Notification type, 'alert', 'message' or 'all'
|
|
* @return {boolean} The model is in API error state
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.isFetchingErrorState = function ( type, sources ) {
|
|
var fetchingSource = 'local';
|
|
|
|
if ( !this.isSourceLocal( sources ) ) {
|
|
fetchingSource = 'foreign';
|
|
}
|
|
return !!( this.apiErrorState[ type ] && this.apiErrorState[ type ][ fetchingSource ] );
|
|
};
|
|
|
|
/**
|
|
* Return the fetch notifications promise
|
|
*
|
|
* @param {string} type Notification type, 'alert', 'message' or 'all'
|
|
* @param {string|string[]} [sources] A name of a source or an array of sources to query
|
|
* @param {Object} [overrideParams] An object defining parameters to override in the API
|
|
* fetching call.
|
|
* @return {jQuery.Promise} Promise that is resolved when notifications are
|
|
* fetched from the API.
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.getFetchNotificationPromise = function ( type, sources, overrideParams ) {
|
|
var fetchingSource = 'local';
|
|
|
|
if ( !this.isSourceLocal( sources ) ) {
|
|
fetchingSource = 'foreign';
|
|
}
|
|
if ( overrideParams || !this.fetchNotificationsPromise[ type ] || !this.fetchNotificationsPromise[ type ][ fetchingSource ] ) {
|
|
this.createNewFetchNotificationPromise( type, sources, overrideParams );
|
|
}
|
|
return this.fetchNotificationsPromise[ type ][ fetchingSource ];
|
|
};
|
|
|
|
/**
|
|
* Get the extra parameters for fetching notifications for a given
|
|
* notification type.
|
|
*
|
|
* @param {string} type Notification type
|
|
* @return {Object} Extra API parameters for fetch notifications
|
|
*/
|
|
mw.echo.api.APIHandler.prototype.getTypeParams = function ( type ) {
|
|
return this.typeParams[ type ];
|
|
};
|
|
} )( mediaWiki, jQuery );
|