Show usernames when display names are matched

Also make our filter function match any substring of
the suggestion index (username + display names), as display
names often contain leading punctuation.

Bug: T266401
Depends-On: I69e5f54f7a8b7ca4126cc3ea513fc96e0a8606fb
Change-Id: I4e7429f8a88c3a82e981f37eb107c2b011482d73
This commit is contained in:
Ed Sanders 2022-09-06 15:41:38 +01:00 committed by Bartosz Dziewoński
parent 79a62f539d
commit 37614a136f

View file

@ -7,6 +7,16 @@
var sequence, var sequence,
controller = require( 'ext.discussionTools.init' ).controller; controller = require( 'ext.discussionTools.init' ).controller;
function sortAuthors( a, b ) {
return a.username < b.username ? -1 : ( a.username === b.username ? 0 : 1 );
}
function hasUser( authors, username ) {
return authors.some( function ( author ) {
return author.username === username;
} );
}
/** /**
* MWUsernameCompletionAction action. * MWUsernameCompletionAction action.
* *
@ -18,8 +28,7 @@ var sequence,
* @param {ve.ui.Surface} surface Surface to act on * @param {ve.ui.Surface} surface Surface to act on
*/ */
function MWUsernameCompletionAction( surface ) { function MWUsernameCompletionAction( surface ) {
var action = this, var action = this;
relevantUserName = mw.config.get( 'wgRelevantUserName' );
// Parent constructor // Parent constructor
MWUsernameCompletionAction.super.call( this, surface ); MWUsernameCompletionAction.super.call( this, surface );
@ -30,20 +39,24 @@ function MWUsernameCompletionAction( surface ) {
this.localUsers = []; this.localUsers = [];
this.ipUsers = []; this.ipUsers = [];
this.surface.authors.forEach( function ( author ) { this.surface.authors.forEach( function ( author ) {
var username = author.username; if ( mw.util.isIPAddress( author.username ) ) {
if ( mw.util.isIPAddress( username ) ) { action.ipUsers.push( author );
action.ipUsers.push( username ); } else if ( author.username !== mw.user.getName() ) {
} else if ( username !== mw.user.getName() ) { action.localUsers.push( author );
action.localUsers.push( username );
} }
} ); } );
// On user talk pages, always list the "owner" of the talk page
var relevantUserName = mw.config.get( 'wgRelevantUserName' );
if ( if (
relevantUserName && relevantUserName &&
relevantUserName !== mw.user.getName() && relevantUserName !== mw.user.getName() &&
this.localUsers.indexOf( relevantUserName ) === -1 !hasUser( this.localUsers, relevantUserName )
) { ) {
this.localUsers.push( relevantUserName ); this.localUsers.push( {
this.localUsers.sort(); username: relevantUserName,
displayNames: []
} );
this.localUsers.sort( sortAuthors );
} }
this.remoteUsers = []; this.remoteUsers = [];
} }
@ -111,19 +124,22 @@ MWUsernameCompletionAction.prototype.getSuggestions = function ( input ) {
} ).then( function ( response ) { } ).then( function ( response ) {
var suggestions = response.query.allusers.filter( function ( user ) { var suggestions = response.query.allusers.filter( function ( user ) {
// API doesn't return IPs // API doesn't return IPs
return action.localUsers.indexOf( user.name ) === -1 && return !hasUser( action.localUsers, user.name ) &&
action.remoteUsers.indexOf( user.name ) === -1 && !hasUser( action.remoteUsers, user.name ) &&
// Exclude users with indefinite sitewide blocks: // Exclude users with indefinite sitewide blocks:
// The only place such users could reply is on their // The only place such users could reply is on their
// own user talk page, and in that case the user // own user talk page, and in that case the user
// will be included in localUsers. // will be included in localUsers.
!( user.blockexpiry === 'infinite' && !user.blockpartial ); !( user.blockexpiry === 'infinite' && !user.blockpartial );
} ).map( function ( user ) { } ).map( function ( user ) {
return user.name; return {
username: user.name,
displayNames: []
};
} ); } );
action.remoteUsers.push.apply( action.remoteUsers, suggestions ); action.remoteUsers.push.apply( action.remoteUsers, suggestions );
action.remoteUsers.sort(); action.remoteUsers.sort( sortAuthors );
action.searchedPrefixes[ input ] = true; action.searchedPrefixes[ input ] = true;
} ); } );
@ -148,6 +164,42 @@ MWUsernameCompletionAction.prototype.getSuggestions = function ( input ) {
} ); } );
}; };
/**
* Compare a suggestion to the normalized user input (lower case)
*
* @param {Mixed} suggestion Suggestion data, string by default
* @param {string} normalizedInput Noramlized user input
* @return {Object} Match object, containing two booleans, `isMatch` and `isExact`
*/
MWUsernameCompletionAction.prototype.compareSuggestionToInput = function ( suggestion, normalizedInput ) {
var normalizedSuggestion = suggestion.username.toLowerCase() + ' ' +
suggestion.displayNames.map( function ( displayName ) {
return displayName.toLowerCase();
} ).join( ' ' );
return {
isMatch: normalizedSuggestion.indexOf( normalizedInput ) !== -1,
isExact: normalizedSuggestion === normalizedInput
};
};
/**
* Create a suggestion from an input
*
* @param {string} input User input
* @return {Mixed} Suggestion data, string by default
*/
MWUsernameCompletionAction.prototype.createSuggestion = function ( input ) {
return {
username: input,
displayNames: []
};
};
MWUsernameCompletionAction.prototype.getMenuItemForSuggestion = function ( suggestion ) {
return new OO.ui.MenuOptionWidget( { data: suggestion.username, label: suggestion.username } );
};
MWUsernameCompletionAction.prototype.getHeaderLabel = function ( input, suggestions ) { MWUsernameCompletionAction.prototype.getHeaderLabel = function ( input, suggestions ) {
if ( suggestions === undefined ) { if ( suggestions === undefined ) {
var $query = $( '<span>' ).text( input ); var $query = $( '<span>' ).text( input );