Sbisson has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/366861 )

Change subject: [WIP] RCFilters: show new changes
......................................................................

[WIP] RCFilters: show new changes

Building on the minimal 'live update' feature,
this change shows an indicator when new changes
for the current filters are detected allowing
the user to fetch them on demand.

Bug: T163426
Change-Id: I6a111d23956bdc04caa4c71e9deede056779aafa
---
M includes/specials/SpecialRecentchanges.php
M languages/i18n/en.json
M languages/i18n/qqq.json
M resources/Resources.php
M resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js
M resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
M resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
M resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
M 
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
M 
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js
M resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js
M resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js
M resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js
13 files changed, 317 insertions(+), 43 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/61/366861/1

diff --git a/includes/specials/SpecialRecentchanges.php 
b/includes/specials/SpecialRecentchanges.php
index 15bbffd..19c94e5 100644
--- a/includes/specials/SpecialRecentchanges.php
+++ b/includes/specials/SpecialRecentchanges.php
@@ -931,15 +931,20 @@
                        $resetLink = $this->makeOptionsLink( $this->msg( 
'rclistfromreset' ),
                                [ 'from' => '' ], $nondefaults );
 
-                       $note .= $this->msg( 'rcnotefrom' )
+                       $noteFromMsg = $this->msg( 'rcnotefrom' )
                                ->numParams( $options['limit'] )
                                ->params(
                                        $lang->userTimeAndDate( 
$options['from'], $user ),
                                        $lang->userDate( $options['from'], 
$user ),
                                        $lang->userTime( $options['from'], 
$user )
                                )
-                               ->numParams( $numRows )
-                               ->parse() . ' ' .
+                               ->numParams( $numRows );
+                       $note .= Html::rawElement(
+                                       'span',
+                                       [ 'class' => 'rcnotefrom' ],
+                                       $noteFromMsg->parse()
+                               ) .
+                               ' ' .
                                Html::rawElement(
                                        'span',
                                        [ 'class' => 'rcoptions-listfromreset' 
],
diff --git a/languages/i18n/en.json b/languages/i18n/en.json
index 929042f..6908cbd 100644
--- a/languages/i18n/en.json
+++ b/languages/i18n/en.json
@@ -1373,6 +1373,8 @@
        "rcfilters-savedqueries-add-new-title": "Save current filter settings",
        "rcfilters-restore-default-filters": "Restore default filters",
        "rcfilters-clear-all-filters": "Clear all filters",
+       "rcfilters-show-new-changes": "Show new changes",
+       "rcfilters-previous-changes-label": "Previously viewed changes",
        "rcfilters-search-placeholder": "Filter recent changes (browse or start 
typing)",
        "rcfilters-invalid-filter": "Invalid filter",
        "rcfilters-empty-filter": "No active filters. All contributions are 
shown.",
diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json
index 719f413..1509e49 100644
--- a/languages/i18n/qqq.json
+++ b/languages/i18n/qqq.json
@@ -1563,6 +1563,8 @@
        "rcfilters-savedqueries-add-new-title": "Title for the popup to add new 
quick link in [[Special:RecentChanges]]. This is for a small popup, please try 
to use a short string.",
        "rcfilters-restore-default-filters": "Label for the button that resets 
filters to defaults",
        "rcfilters-clear-all-filters": "Title for the button that clears all 
filters",
+       "rcfilters-show-new-changes": "Label for the button to show new 
changes.",
+       "rcfilters-previous-changes-label": "Label to indicate the changes 
below have been previously viewed.",
        "rcfilters-search-placeholder": "Placeholder for the filter search 
input.",
        "rcfilters-invalid-filter": "A label for an invalid filter.",
        "rcfilters-empty-filter": "Placeholder for the filter list when no 
filters were chosen.",
diff --git a/resources/Resources.php b/resources/Resources.php
index 33fb8f1..5ab66fb 100644
--- a/resources/Resources.php
+++ b/resources/Resources.php
@@ -1853,6 +1853,8 @@
                        'rcfilters-savedqueries-cancel-label',
                        'rcfilters-restore-default-filters',
                        'rcfilters-clear-all-filters',
+                       'rcfilters-show-new-changes',
+                       'rcfilters-previous-changes-label',
                        'rcfilters-search-placeholder',
                        'rcfilters-invalid-filter',
                        'rcfilters-empty-filter',
diff --git 
a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js 
b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js
index 49c0b82..ac54944 100644
--- 
a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js
+++ 
b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js
@@ -11,6 +11,10 @@
                OO.EventEmitter.call( this );
 
                this.valid = true;
+               this.newChangesExist = false;
+               this.nextFrom = null;
+               this.liveUpdate = false;
+               this.changesList = null;
        };
 
        /* Initialization */
@@ -27,10 +31,26 @@
 
        /**
         * @event update
-        * @param {jQuery|string} changesListContent
-        * @param {jQuery} $fieldset
+        * @param {jQuery|string} $changesListContent List of changes
+        * @param {jQuery} $fieldset Server-generated form
+        * @param {boolean} isInitialDOM Whether the previous dom variables are 
from the initial page load
+        * @param {int|null} rcId Id of the last change viewed prior to this 
update
         *
-        * The list of change is now up to date
+        * The list of changes has been updated
+        */
+
+       /**
+        * @event newChangesExist
+        * @param {boolean} newChangesExist
+        *
+        * The existence of changes newer than those currently displayed has 
changed.
+        */
+
+       /**
+        * @event liveUpdateChange
+        * @param {boolean} enable
+        *
+        * The state of the 'live update' feature has changed.
         */
 
        /* Methods */
@@ -43,6 +63,7 @@
        mw.rcfilters.dm.ChangesListViewModel.prototype.invalidate = function () 
{
                if ( this.valid ) {
                        this.valid = false;
+                       this.setNewChangesExist( false );
                        this.emit( 'invalidate' );
                }
        };
@@ -53,10 +74,74 @@
         * @param {jQuery|string} changesListContent
         * @param {jQuery} $fieldset
         * @param {boolean} [isInitialDOM] Using the initial (already attached) 
DOM elements
+        * @param {boolean} [fromLiveUpdate] These are new changes fetched via 
Live Update
+        * @fires update
         */
-       mw.rcfilters.dm.ChangesListViewModel.prototype.update = function ( 
changesListContent, $fieldset, isInitialDOM ) {
+       mw.rcfilters.dm.ChangesListViewModel.prototype.update = function ( 
changesListContent, $fieldset, isInitialDOM, fromLiveUpdate ) {
+               var rcId = fromLiveUpdate ? this.extractTopRcId( 
this.changesList ) : null;
                this.valid = true;
-               this.emit( 'update', changesListContent, $fieldset, 
isInitialDOM );
+               this.changesList = changesListContent;
+               this.extractNextFrom( $fieldset );
+               this.emit( 'update', changesListContent, $fieldset, 
isInitialDOM, rcId );
+       };
+
+       /**
+        * Specify whether new changes exist
+        *
+        * @param {boolean} newChangesExist
+        * @fires newChangesExist
+        */
+       mw.rcfilters.dm.ChangesListViewModel.prototype.setNewChangesExist = 
function ( newChangesExist ) {
+               if ( newChangesExist !== this.newChangesExist ) {
+                       this.newChangesExist = newChangesExist;
+                       this.emit( 'newChangesExist', newChangesExist );
+               }
+       };
+
+       /**
+        * Extract the value of the 'from' parameter from a link in the field 
set
+        *
+        * @param {jQuery} $fieldSet
+        */
+       mw.rcfilters.dm.ChangesListViewModel.prototype.extractNextFrom = 
function ( $fieldSet ) {
+               this.nextFrom = $fieldSet.find( '.rclistfrom > a' ).data( 
'params' ).from;
+       };
+
+       /**
+        * Extract the RC ID of the first change in the list
+        *
+        * @param {jQuery} $changesList
+        * @return {string} RC ID of the first change in $changesList
+        */
+       mw.rcfilters.dm.ChangesListViewModel.prototype.extractTopRcId = 
function ( $changesList ) {
+               return $changesList.find( '[data-mw-revid]:first' ).data( 
'mw-revid' );
+       };
+
+       /**
+        * @return {string} The 'from' parameter that can be used to query new 
changes
+        */
+       mw.rcfilters.dm.ChangesListViewModel.prototype.getNextFrom = function 
() {
+               return this.nextFrom;
+       };
+
+       /**
+        * Toggle the 'live update' feature on/off
+        *
+        * @param {boolean} enable
+        */
+       mw.rcfilters.dm.ChangesListViewModel.prototype.toggleLiveUpdate = 
function ( enable ) {
+               enable = enable === undefined ? !this.liveUpdate : enable;
+               if ( enable !== this.liveUpdate ) {
+                       this.liveUpdate = enable;
+                       this.emit( 'liveUpdateChange', this.liveUpdate );
+               }
+       };
+
+       /**
+        * @return {boolean} The 'live update' feature is enabled
+        */
+       mw.rcfilters.dm.ChangesListViewModel.prototype.getLiveUpdate = function 
() {
+               return this.liveUpdate;
        };
 
 }( mediaWiki ) );
diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js 
b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
index 5ebec27..69cc88d 100644
--- a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
+++ b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
@@ -11,7 +11,7 @@
                this.filtersModel = filtersModel;
                this.changesListModel = changesListModel;
                this.savedQueriesModel = savedQueriesModel;
-               this.requestCounter = 0;
+               this.requestCounter = {};
                this.baseFilterState = {};
                this.uriProcessor = null;
                this.initializing = false;
@@ -378,9 +378,12 @@
 
        /**
         * Enable or disable live updates.
-        * @param {boolean} enable True to enable, false to disable
         */
-       mw.rcfilters.Controller.prototype.toggleLiveUpdate = function ( enable 
) {
+       mw.rcfilters.Controller.prototype.toggleLiveUpdate = function () {
+               var enable;
+
+               this.changesListModel.toggleLiveUpdate();
+               enable = this.changesListModel.getLiveUpdate();
                if ( enable && !this.liveUpdateTimeout ) {
                        this._scheduleLiveUpdate();
                } else if ( !enable && this.liveUpdateTimeout ) {
@@ -402,14 +405,56 @@
         * @private
         */
        mw.rcfilters.Controller.prototype._doLiveUpdate = function () {
-               var controller = this;
-               this.updateChangesList( {}, true )
-                       .always( function () {
-                               if ( controller.liveUpdateTimeout ) {
-                                       // Live update was not disabled in the 
meantime
-                                       controller._scheduleLiveUpdate();
+               this._checkForNewChanges()
+                       .then( function ( data ) {
+                               if ( data.changes !== 'NO_RESULTS' ) {
+                                       
this.changesListModel.setNewChangesExist( true );
+                               } else {
+                                       if ( this.liveUpdateTimeout ) {
+                                               this._scheduleLiveUpdate();
+                                       }
                                }
-                       } );
+                       }.bind( this ) );
+       };
+
+       /**
+        * Check if new changes, newer than those currently shown, are available
+        *
+        * @return {jQuery.Promise} Promise object that resolves after trying
+        * to fetch 1 change newer than the last known 'from' parameter value
+        *
+        * @private
+        */
+       mw.rcfilters.Controller.prototype._checkForNewChanges = function () {
+               return this._fetchChangesList(
+                       'liveUpdate',
+                       {
+                               limit: 1,
+                               from: this.changesListModel.getNextFrom()
+                       }
+               );
+       };
+
+       /**
+        * Show the new changes
+        *
+        * @return {jQuery.Promise} Promise object that resolves after the
+        * new changes have been fetched and probably displayed
+        */
+       mw.rcfilters.Controller.prototype.showNewChanges = function () {
+               this.changesListModel.invalidate();
+               return this._fetchChangesList()
+                       .then(
+                               // Success
+                               function ( pieces ) {
+                                       var $changesListContent = 
pieces.changes,
+                                               $fieldset = pieces.fieldset;
+                                       this.changesListModel.update( 
$changesListContent, $fieldset, false, true );
+                                       if ( 
this.changesListModel.getLiveUpdate() ) {
+                                               this._scheduleLiveUpdate();
+                                       }
+                               }.bind( this )
+                       );
        };
 
        /**
@@ -844,15 +889,33 @@
        /**
         * Fetch the list of changes from the server for the current filters
         *
+        * @param {string} [counterId='updateChangesList'] Id for this request. 
To allow concurrent requests
+        *  not to invalidate each others.
+        * @param {object} [params={}] Parameters to add to the query
+        *
         * @return {jQuery.Promise} Promise object that will resolve with the 
changes list
         *  or with a string denoting no results.
         */
-       mw.rcfilters.Controller.prototype._fetchChangesList = function () {
+       mw.rcfilters.Controller.prototype._fetchChangesList = function ( 
counterId, params ) {
                var uri = this._getUpdatedUri(),
-                       requestId = ++this.requestCounter,
-                       latestRequest = function () {
-                               return requestId === this.requestCounter;
-                       }.bind( this );
+                       requestId,
+                       latestRequest;
+
+               counterId = counterId || 'updateChangesList';
+               params = params || {};
+
+               uri.query = $.extend(
+                       true,
+                       {},
+                       uri.query,
+                       params
+               );
+
+               this.requestCounter[ counterId ] = this.requestCounter[ 
counterId ] || 0;
+               requestId = ++this.requestCounter[ counterId ];
+               latestRequest = function () {
+                       return requestId === this.requestCounter[ counterId ];
+               }.bind( this );
 
                return $.ajax( uri.toString(), { contentType: 'html' } )
                        .then(
diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js 
b/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
index 6cd2d0b..fd3d7df 100644
--- a/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
+++ b/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
@@ -16,13 +16,13 @@
                                $overlay = $( '<div>' )
                                        .addClass( 'mw-rcfilters-ui-overlay' ),
                                filtersWidget = new 
mw.rcfilters.ui.FilterWrapperWidget(
-                                       controller, filtersModel, 
savedQueriesModel, { $overlay: $overlay } );
+                                       controller, filtersModel, 
savedQueriesModel, changesListModel, { $overlay: $overlay } );
 
                        // TODO: The changesListWrapperWidget should be able to 
initialize
                        // after the model is ready.
                        // eslint-disable-next-line no-new
                        new mw.rcfilters.ui.ChangesListWrapperWidget(
-                               filtersModel, changesListModel, $( 
'.mw-changeslist, .mw-changeslist-empty' ) );
+                               filtersModel, changesListModel, controller, $( 
'.mw-changeslist, .mw-changeslist-empty' ) );
 
                        controller.initialize(
                                mw.config.get( 'wgStructuredChangeFilters' ),
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less 
b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
index 6277fd9..ab2ab35 100644
--- a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
+++ b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
@@ -2,11 +2,6 @@
 .client-js{
        .rcoptions {
                border: 0;
-               border-bottom: 1px solid #a2a9b1;
-
-               legend {
-                       display: none;
-               }
        }
 
        .rcfilters-head {
diff --git 
a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
 
b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
index 89acdc0..b8b7080 100644
--- 
a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
+++ 
b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
@@ -1,6 +1,26 @@
 @import 'mw.rcfilters.mixins';
 
 .mw-rcfilters-ui-changesListWrapperWidget {
+
+       &-newChanges {
+               min-height: 34px;
+               margin: 10px 0 10px 0;
+               text-align: center;
+       }
+
+       &-previousChangesIndicator {
+               margin: 10px 0 10px 0;
+               color: #36c;
+               border-top: 2px solid #36c;
+               text-align: center;
+
+               &:hover {
+                       color: #72777d;
+                       border-top-color: #72777d;
+                       cursor: pointer;
+               }
+       }
+
        &-results {
                width: 35em;
                margin: 5em auto;
diff --git 
a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js
 
b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js
index 6512f04..7022cce 100644
--- 
a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js
+++ 
b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js
@@ -8,12 +8,14 @@
         * @constructor
         * @param {mw.rcfilters.dm.FiltersViewModel} filtersViewModel View model
         * @param {mw.rcfilters.dm.ChangesListViewModel} changesListViewModel 
View model
+        * @param {mw.rcfilters.Controller} controller
         * @param {jQuery} $changesListRoot Root element of the changes list to 
attach to
-        * @param {Object} config Configuration object
+        * @param {Object} [config] Configuration object
         */
        mw.rcfilters.ui.ChangesListWrapperWidget = function 
MwRcfiltersUiChangesListWrapperWidget(
                filtersViewModel,
                changesListViewModel,
+               controller,
                $changesListRoot,
                config
        ) {
@@ -28,6 +30,7 @@
 
                this.filtersViewModel = filtersViewModel;
                this.changesListViewModel = changesListViewModel;
+               this.controller = controller;
 
                // Events
                this.filtersViewModel.connect( this, {
@@ -36,7 +39,8 @@
                } );
                this.changesListViewModel.connect( this, {
                        invalidate: 'onModelInvalidate',
-                       update: 'onModelUpdate'
+                       update: 'onModelUpdate',
+                       newChangesExist: 'onNewChangesExist'
                } );
 
                this.$element
@@ -46,6 +50,8 @@
 
                // Set up highlight containers
                this.setupHighlightContainers( this.$element );
+
+               this.setupNewChangesButtonContainer( this.$element );
        };
 
        /* Initialization */
@@ -89,12 +95,17 @@
         * @param {jQuery|string} $changesListContent The content of the 
updated changes list
         * @param {jQuery} $fieldset The content of the updated fieldset
         * @param {boolean} isInitialDOM Whether $changesListContent is the 
existing (already attached) DOM
+        * @param {int} rcId ID of the last change that was seen prior to the 
current data update
         */
-       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelUpdate = 
function ( $changesListContent, $fieldset, isInitialDOM ) {
+       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelUpdate = 
function (
+               $changesListContent, $fieldset, isInitialDOM, rcId
+       ) {
                var conflictItem,
                        $message = $( '<div>' )
                                .addClass( 
'mw-rcfilters-ui-changesListWrapperWidget-results' ),
-                       isEmpty = $changesListContent === 'NO_RESULTS';
+                       isEmpty = $changesListContent === 'NO_RESULTS',
+                       $lastSeen,
+                       $indicator;
 
                this.$element.toggleClass( 'mw-changeslist', !isEmpty );
                if ( isEmpty ) {
@@ -132,6 +143,31 @@
                        // Apply highlight
                        this.applyHighlight();
 
+                       // add a separator between old and new changes
+                       if ( rcId ) {
+                               $lastSeen = this.$element.find( 
'[data-mw-revid="' + rcId + '"]' );
+                               if ( $lastSeen ) {
+
+                                       $indicator = $( '<div>' )
+                                               .addClass( 
'mw-rcfilters-ui-changesListWrapperWidget-previousChangesIndicator' )
+                                               .text( mw.message( 
'rcfilters-previous-changes-label' ).text() );
+
+                                       $indicator.on( 'click', function () {
+                                               $indicator.detach();
+                                       } );
+
+                                       if ( $lastSeen.is( 'tr' ) ) {
+                                               // TODO: figure out how to 
handle enhanced rc
+                                       } else {
+                                               if ( $lastSeen.is( 
':first-child' ) ) {
+                                                       $lastSeen = 
$lastSeen.parent().prev();
+                                               }
+
+                                               $lastSeen.before( $indicator );
+                                       }
+                               }
+                       }
+
                        if ( !isInitialDOM ) {
                                // Make sure enhanced RC re-initializes 
correctly
                                mw.hook( 'wikipage.content' ).fire( 
this.$element );
@@ -141,6 +177,44 @@
        };
 
        /**
+        * Respond to changes list model newChangesExist
+        *
+        * @param {boolean} newChangesExist Whether new changes exist
+        */
+       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onNewChangesExist = 
function ( newChangesExist ) {
+               this.showNewChangesLink.toggle( newChangesExist );
+       };
+
+       /**
+        * Respond to the user clicking the 'show new changes' button
+        */
+       
mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onShowNewChangesClick = 
function () {
+               this.controller.showNewChanges();
+       };
+
+       /**
+        * Setup the container for the 'new changes' button.
+        *
+        * @param {jQuery} $content
+        */
+       
mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupNewChangesButtonContainer
 = function ( $content ) {
+               this.showNewChangesLink = new OO.ui.ButtonWidget( {
+                       framed: false,
+                       label: mw.message( 'rcfilters-show-new-changes' 
).text(),
+                       classes: [ 
'mw-rcfilters-ui-changesListWrapperWidget-newChanges-Button' ],
+                       flags: [ 'progressive' ]
+               } );
+               this.showNewChangesLink.connect( this, { click: 
'onShowNewChangesClick' } );
+               this.showNewChangesLink.toggle( false );
+
+               $content.before(
+                       $( '<div>' )
+                               .addClass( 
'mw-rcfilters-ui-changesListWrapperWidget-newChanges' )
+                               .append( this.showNewChangesLink.$element )
+               );
+       };
+
+       /**
         * Set up the highlight containers with all color circle indicators.
         *
         * @param {jQuery|string} $content The content of the updated changes 
list
diff --git 
a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js 
b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js
index 9b4ce7f..3e2721e 100644
--- 
a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js
+++ 
b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js
@@ -9,11 +9,14 @@
         * @param {mw.rcfilters.Controller} controller Controller
         * @param {mw.rcfilters.dm.FiltersViewModel} model View model
         * @param {mw.rcfilters.dm.SavedQueriesModel} savedQueriesModel Saved 
queries model
+        * @param {mw.rcfilters.dm.ChangesListViewModel} changesListModel
         * @param {Object} [config] Configuration object
         * @cfg {Object} [filters] A definition of the filter groups in this 
list
         * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for 
popups
         */
-       mw.rcfilters.ui.FilterWrapperWidget = function 
MwRcfiltersUiFilterWrapperWidget( controller, model, savedQueriesModel, config 
) {
+       mw.rcfilters.ui.FilterWrapperWidget = function 
MwRcfiltersUiFilterWrapperWidget(
+               controller, model, savedQueriesModel, changesListModel, config
+       ) {
                var $bottom;
                config = config || {};
 
@@ -35,7 +38,8 @@
                );
 
                this.liveUpdateButton = new 
mw.rcfilters.ui.LiveUpdateButtonWidget(
-                       this.controller
+                       this.controller,
+                       changesListModel
                );
 
                this.numChangesWidget = new 
mw.rcfilters.ui.ChangesLimitButtonWidget(
diff --git 
a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js 
b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js
index 0abaff2..aa33f74 100644
--- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js
+++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js
@@ -149,11 +149,22 @@
                        this.$element.find( '.mw-recentchanges-table' 
).detach();
                        this.$element.find( 'hr' ).detach();
                }
+
                if ( !this.$element.find( '.rcshowhide' ).contents().length ) {
                        this.$element.find( '.rcshowhide' ).detach();
                        // If we're hiding rcshowhide, the '<br>'s are around 
it,
                        // there's no need for them either.
                        this.$element.find( 'br' ).detach();
                }
+
+               this.$element.find( 'legend' ).detach();
+
+               this.$element.find(
+                       '.rclistfrom, .rcnotefrom, .rcoptions-listfromreset'
+               ).detach();
+
+               if ( this.$element.text().trim() === '' ) {
+                       this.$element.detach();
+               }
        };
 }( mediaWiki ) );
diff --git 
a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js
 
b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js
index 90ee4d7..bd8f0e1 100644
--- 
a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js
+++ 
b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js
@@ -6,9 +6,10 @@
         *
         * @constructor
         * @param {mw.rcfilters.Controller} controller
-        * @param {Object} config Configuration object
+        * @param {mw.rcfilters.dm.ChangesListViewModel} changesListModel
+        * @param {Object} [config] Configuration object
         */
-       mw.rcfilters.ui.LiveUpdateButtonWidget = function 
MwRcfiltersUiLiveUpdateButtonWidget( controller, config ) {
+       mw.rcfilters.ui.LiveUpdateButtonWidget = function 
MwRcfiltersUiLiveUpdateButtonWidget( controller, changesListModel, config ) {
                config = config || {};
 
                // Parent
@@ -18,9 +19,11 @@
                }, config ) );
 
                this.controller = controller;
+               this.model = changesListModel;
 
                // Events
-               this.connect( this, { change: 'onChange' } );
+               this.connect( this, { click: 'onClick' } );
+               this.model.connect( this, { liveUpdateChange: 
'onLiveUpdateChange' } );
 
                this.$element.addClass( 
'mw-rcfilters-ui-liveUpdateButtonWidget' );
        };
@@ -32,11 +35,19 @@
        /* Methods */
 
        /**
-        * Respond to the button being toggled.
-        * @param {boolean} enable Whether the button is now pressed/enabled
+        * Respond to the button being clicked
         */
-       mw.rcfilters.ui.LiveUpdateButtonWidget.prototype.onChange = function ( 
enable ) {
-               this.controller.toggleLiveUpdate( enable );
+       mw.rcfilters.ui.LiveUpdateButtonWidget.prototype.onClick = function () {
+               this.controller.toggleLiveUpdate();
+       };
+
+       /**
+        * Respond to the 'live update' feature being turned on/off
+        *
+        * @param {boolean} enable Whether the 'live update' feature is now 
on/off
+        */
+       mw.rcfilters.ui.LiveUpdateButtonWidget.prototype.onLiveUpdateChange = 
function ( enable ) {
+               this.setValue( enable );
        };
 
 }( mediaWiki ) );

-- 
To view, visit https://gerrit.wikimedia.org/r/366861
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6a111d23956bdc04caa4c71e9deede056779aafa
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Sbisson <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to