Catrope has uploaded a new change for review. https://gerrit.wikimedia.org/r/273569
Change subject: [WIP] In cross-wiki notifications, sort wikis by timestamp of most recent notification ...................................................................... [WIP] In cross-wiki notifications, sort wikis by timestamp of most recent notification Also make the wiki mentioned in the message be the one with the most recent notification. ForeignNotifications tracks timestamps per wiki per section, and exposes these through getWikiTimestamp(). ApiEchoNotifications adds these timestamps to the sources manifest, and also sorts the list of wikis by timestamp (it'd be nicer to do this in ForeignPresentationModel instead, but then we'd have to create a new ForeignNotifications instance which causes a duplicated DB query). NotificationsModel receives the timestamp for its wiki as its fallback timestamp, and makes getTimestamp() return this value during the pre-population phase. This causes its parent to automatically sort it correctly. Change-Id: Ie083fbb1ccaf74fbe804633d87ef03c9e71b120f --- M includes/ForeignNotifications.php M includes/api/ApiEchoNotifications.php M modules/viewmodel/mw.echo.dm.NotificationGroupItem.js M modules/viewmodel/mw.echo.dm.NotificationsModel.js 4 files changed, 44 insertions(+), 2 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Echo refs/changes/69/273569/1 diff --git a/includes/ForeignNotifications.php b/includes/ForeignNotifications.php index d75fcba..ccf18ab 100644 --- a/includes/ForeignNotifications.php +++ b/includes/ForeignNotifications.php @@ -22,6 +22,11 @@ protected $timestamps = array( EchoAttributeManager::ALERT => false, EchoAttributeManager::MESSAGE => false ); /** + * @var array [(str) wiki => [ (str) section => (MWTimestamp) timestamp, ...], ...] + */ + protected $wikiTimestamps = array(); + + /** * @var bool */ protected $populated = false; @@ -92,6 +97,25 @@ return isset( $this->wikis[$section] ) ? $this->wikis[$section] : array(); } + public function getWikiTimestamp( $wiki, $section = null ) { + $this->populate(); + if ( !isset( $this->wikiTimestamps[$wiki] ) ) { + return false; + } + if ( $section === null ) { + $max = false; + foreach ( $this->wikiTimestamps[$wiki] as $section => $ts ) { + // $ts < $max = invert 0 + // $ts > $max = invert 1 + if ( $max === false || $ts->diff( $max )->invert === 1 ) { + $max = $ts; + } + } + return $max; + } + return isset( $this->wikiTimestamps[$wiki][$section] ) ? $this->wikiTimestamps[$wiki][$section] : false; + } + protected function populate() { if ( $this->populated ) { return; @@ -118,6 +142,8 @@ $this->wikis[$section][] = $wiki; $timestamp = new MWTimestamp( $data['ts'] ); + $this->wikiTimestamps[$wiki][$section] = $timestamp; + // We need $this->timestamp[$section] to be the max timestamp // across all wikis. // $timestamp < $this->timestamps[$section] = invert 0 diff --git a/includes/api/ApiEchoNotifications.php b/includes/api/ApiEchoNotifications.php index 4353134..33d08a3 100644 --- a/includes/api/ApiEchoNotifications.php +++ b/includes/api/ApiEchoNotifications.php @@ -89,6 +89,11 @@ // can be queried from if ( $foreignNotifications ) { $result['sources'] = $foreignNotifications->getApiEndpoints( $foreignNotifications->getWikis() ); + // Add timestamp information + foreach ( $result['sources'] as $wiki => &$data ) { + // FIXME: getWikiTimestamp() needs $section but we don't have that here + $data['ts'] = $foreignNotifications->getWikiTimestamp( $wiki )->getTimestamp( TS_MW ); + } } } @@ -285,6 +290,13 @@ $wikis = $foreignNotifications->getWikis( $section ); $count = $foreignNotifications->getCount( $section ); + // Sort wikis by timestamp, in descending order (newest first) + usort( $wikis, function ( $a, $b ) use ( $foreignNotifications, $section ) { + $aTimestamp = $foreignNotifications->getWikiTimestamp( $a, $section ) ?: new MWTimestamp( 0 ); + $bTimestamp = $foreignNotifications->getWikiTimestamp( $b, $section ) ?: new MWTimestamp( 0 ); + return $bTimestamp->getTimestamp( TS_UNIX ) - $aTimestamp->getTimestamp( TS_UNIX ); + } ); + $row = new StdClass; $row->event_id = -1; $row->event_type = 'foreign'; diff --git a/modules/viewmodel/mw.echo.dm.NotificationGroupItem.js b/modules/viewmodel/mw.echo.dm.NotificationGroupItem.js index b8e617a..4c34e7b 100644 --- a/modules/viewmodel/mw.echo.dm.NotificationGroupItem.js +++ b/modules/viewmodel/mw.echo.dm.NotificationGroupItem.js @@ -65,7 +65,8 @@ source: source, foreign: this.foreign, title: this.sources[ source ].title, - removeReadNotifications: this.removeReadNotifications + removeReadNotifications: this.removeReadNotifications, + timestamp: this.sources[ source ].ts } ); items.push( item ); diff --git a/modules/viewmodel/mw.echo.dm.NotificationsModel.js b/modules/viewmodel/mw.echo.dm.NotificationsModel.js index 79f3715..d9e708d 100644 --- a/modules/viewmodel/mw.echo.dm.NotificationsModel.js +++ b/modules/viewmodel/mw.echo.dm.NotificationsModel.js @@ -18,6 +18,8 @@ * the source of the notification items for the network handler. * @cfg {number} [limit=25] Notification limit * @cfg {string} [userLang] User language + * @cfg {number} [timestamp] Timestamp (in MW format) to return from #getTimestamp when + * there are no items; use this if the timestamp is known ahead of time (before population). * @cfg {boolean} [foreign] The model's source is foreign * @cfg {boolean} [removeReadNotifications=false] Remove read notifications completely. This * means the model will only contain unread notifications. This is useful for @@ -36,6 +38,7 @@ this.source = config.source || 'local'; this.id = config.id || this.source; this.title = config.title || ''; + this.fallbackTimestamp = config.timestamp; this.markingAllAsRead = false; this.autoMarkReadInProcess = false; @@ -682,7 +685,7 @@ // This is a sorted list, so the top (first) item is also the 'latest' // item for this purpose. - return items[ 0 ] && items[ 0 ].getTimestamp(); + return ( items[ 0 ] && items[ 0 ].getTimestamp() ) || this.fallbackTimestamp; }; /** -- To view, visit https://gerrit.wikimedia.org/r/273569 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie083fbb1ccaf74fbe804633d87ef03c9e71b120f Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Echo Gerrit-Branch: master Gerrit-Owner: Catrope <roan.katt...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits