Order room completions more intuitively

by index of the query in displayedAlias and then length of displayedAlias. (So that aliases where the query appears earlier in the string appear first and if the query is in the same index for two aliases, the shorter one appears first).
pull/21833/head
Luke Barnard 2017-08-02 09:35:07 +01:00
parent ff378cc85a
commit 8053d2933a
1 changed files with 24 additions and 6 deletions

View File

@ -23,35 +23,51 @@ import FuzzyMatcher from './FuzzyMatcher';
import {PillCompletion} from './Components'; import {PillCompletion} from './Components';
import {getDisplayAliasForRoom} from '../Rooms'; import {getDisplayAliasForRoom} from '../Rooms';
import sdk from '../index'; import sdk from '../index';
import _sortBy from 'lodash/sortBy';
const ROOM_REGEX = /(?=#)(\S*)/g; const ROOM_REGEX = /(?=#)(\S*)/g;
let instance = null; let instance = null;
function score(query, space) {
const index = space.indexOf(query);
if (index === -1) {
return Infinity;
} else {
return index;
}
}
export default class RoomProvider extends AutocompleteProvider { export default class RoomProvider extends AutocompleteProvider {
constructor() { constructor() {
super(ROOM_REGEX); super(ROOM_REGEX);
this.matcher = new FuzzyMatcher([], { this.matcher = new FuzzyMatcher([], {
keys: ['name', 'roomId', 'aliases'], keys: ['displayedAlias', 'name', 'roomId'],
}); });
} }
async getCompletions(query: string, selection: {start: number, end: number}, force = false) { async getCompletions(query: string, selection: {start: number, end: number}, force = false) {
const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar'); const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar');
let client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
let completions = []; let completions = [];
const {command, range} = this.getCurrentCommand(query, selection, force); const {command, range} = this.getCurrentCommand(query, selection, force);
if (command) { if (command) {
// the only reason we need to do this is because Fuse only matches on properties // the only reason we need to do this is because Fuse only matches on properties
this.matcher.setObjects(client.getRooms().filter(room => !!room && !!getDisplayAliasForRoom(room)).map(room => { this.matcher.setObjects(client.getRooms().filter(
(room) => !!room && !!getDisplayAliasForRoom(room),
).map((room) => {
return { return {
room: room, room: room,
name: room.name, name: room.name,
aliases: room.getAliases(), displayedAlias: getDisplayAliasForRoom(room),
}; };
})); }));
completions = this.matcher.match(command[0]).map(room => { completions = this.matcher.match(command[0]);
completions = _sortBy(completions, [
(c) => score(query, c.displayedAlias),
(c) => c.displayedAlias.length,
]).map((room) => {
const displayAlias = getDisplayAliasForRoom(room.room) || room.roomId; const displayAlias = getDisplayAliasForRoom(room.room) || room.roomId;
return { return {
completion: displayAlias, completion: displayAlias,
@ -62,7 +78,9 @@ export default class RoomProvider extends AutocompleteProvider {
), ),
range, range,
}; };
}).filter(completion => !!completion.completion && completion.completion.length > 0).slice(0, 4); })
.filter((completion) => !!completion.completion && completion.completion.length > 0)
.slice(0, 4);
} }
return completions; return completions;
} }