merge develop
This commit is contained in:
commit
efdc5430d7
176 changed files with 7537 additions and 3401 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Copyright 2016 Aviral Dasgupta
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
Copyright 2017, 2018 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -57,14 +57,14 @@ export default class AutocompleteProvider {
|
|||
|
||||
let match;
|
||||
while ((match = commandRegex.exec(query)) != null) {
|
||||
let matchStart = match.index,
|
||||
matchEnd = matchStart + match[0].length;
|
||||
if (selection.start <= matchEnd && selection.end >= matchStart) {
|
||||
const start = match.index;
|
||||
const end = start + match[0].length;
|
||||
if (selection.start <= end && selection.end >= start) {
|
||||
return {
|
||||
command: match,
|
||||
range: {
|
||||
start: matchStart,
|
||||
end: matchEnd,
|
||||
start,
|
||||
end,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright 2016 Aviral Dasgupta
|
||||
Copyright 2017 New Vector Ltd
|
||||
Copyright 2017, 2018 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -18,7 +18,9 @@ limitations under the License.
|
|||
// @flow
|
||||
|
||||
import type {Component} from 'react';
|
||||
import {Room} from 'matrix-js-sdk';
|
||||
import CommandProvider from './CommandProvider';
|
||||
import CommunityProvider from './CommunityProvider';
|
||||
import DuckDuckGoProvider from './DuckDuckGoProvider';
|
||||
import RoomProvider from './RoomProvider';
|
||||
import UserProvider from './UserProvider';
|
||||
|
@ -48,6 +50,7 @@ const PROVIDERS = [
|
|||
EmojiProvider,
|
||||
NotifProvider,
|
||||
CommandProvider,
|
||||
CommunityProvider,
|
||||
DuckDuckGoProvider,
|
||||
];
|
||||
|
||||
|
@ -55,7 +58,7 @@ const PROVIDERS = [
|
|||
const PROVIDER_COMPLETION_TIMEOUT = 3000;
|
||||
|
||||
export default class Autocompleter {
|
||||
constructor(room) {
|
||||
constructor(room: Room) {
|
||||
this.room = room;
|
||||
this.providers = PROVIDERS.map((p) => {
|
||||
return new p(room);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
Copyright 2016 Aviral Dasgupta
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
Copyright 2018 Michael Telatynski <7t3chguy@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -17,104 +18,16 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { _t, _td } from '../languageHandler';
|
||||
import {_t} from '../languageHandler';
|
||||
import AutocompleteProvider from './AutocompleteProvider';
|
||||
import FuzzyMatcher from './FuzzyMatcher';
|
||||
import {TextualCompletion} from './Components';
|
||||
import type {SelectionRange} from './Autocompleter';
|
||||
import type {Completion, SelectionRange} from "./Autocompleter";
|
||||
import {CommandMap} from '../SlashCommands';
|
||||
|
||||
// TODO merge this with the factory mechanics of SlashCommands?
|
||||
// Warning: Since the description string will be translated in _t(result.description), all these strings below must be in i18n/strings/en_EN.json file
|
||||
const COMMANDS = [
|
||||
{
|
||||
command: '/me',
|
||||
args: '<message>',
|
||||
description: _td('Displays action'),
|
||||
},
|
||||
{
|
||||
command: '/ban',
|
||||
args: '<user-id> [reason]',
|
||||
description: _td('Bans user with given id'),
|
||||
},
|
||||
{
|
||||
command: '/unban',
|
||||
args: '<user-id>',
|
||||
description: _td('Unbans user with given id'),
|
||||
},
|
||||
{
|
||||
command: '/op',
|
||||
args: '<user-id> [<power-level>]',
|
||||
description: _td('Define the power level of a user'),
|
||||
},
|
||||
{
|
||||
command: '/deop',
|
||||
args: '<user-id>',
|
||||
description: _td('Deops user with given id'),
|
||||
},
|
||||
{
|
||||
command: '/invite',
|
||||
args: '<user-id>',
|
||||
description: _td('Invites user with given id to current room'),
|
||||
},
|
||||
{
|
||||
command: '/join',
|
||||
args: '<room-alias>',
|
||||
description: _td('Joins room with given alias'),
|
||||
},
|
||||
{
|
||||
command: '/part',
|
||||
args: '[<room-alias>]',
|
||||
description: _td('Leave room'),
|
||||
},
|
||||
{
|
||||
command: '/topic',
|
||||
args: '<topic>',
|
||||
description: _td('Sets the room topic'),
|
||||
},
|
||||
{
|
||||
command: '/kick',
|
||||
args: '<user-id> [reason]',
|
||||
description: _td('Kicks user with given id'),
|
||||
},
|
||||
{
|
||||
command: '/nick',
|
||||
args: '<display-name>',
|
||||
description: _td('Changes your display nickname'),
|
||||
},
|
||||
{
|
||||
command: '/ddg',
|
||||
args: '<query>',
|
||||
description: _td('Searches DuckDuckGo for results'),
|
||||
},
|
||||
{
|
||||
command: '/tint',
|
||||
args: '<color1> [<color2>]',
|
||||
description: _td('Changes colour scheme of current room'),
|
||||
},
|
||||
{
|
||||
command: '/verify',
|
||||
args: '<user-id> <device-id> <device-signing-key>',
|
||||
description: _td('Verifies a user, device, and pubkey tuple'),
|
||||
},
|
||||
{
|
||||
command: '/ignore',
|
||||
args: '<user-id>',
|
||||
description: _td('Ignores a user, hiding their messages from you'),
|
||||
},
|
||||
{
|
||||
command: '/unignore',
|
||||
args: '<user-id>',
|
||||
description: _td('Stops ignoring a user, showing their messages going forward'),
|
||||
},
|
||||
{
|
||||
command: '/devtools',
|
||||
args: '',
|
||||
description: _td('Opens the Developer Tools dialog'),
|
||||
},
|
||||
// Omitting `/markdown` as it only seems to apply to OldComposer
|
||||
];
|
||||
const COMMANDS = Object.values(CommandMap);
|
||||
|
||||
const COMMAND_RE = /(^\/\w*)/g;
|
||||
const COMMAND_RE = /(^\/\w*)(?: .*)?/g;
|
||||
|
||||
export default class CommandProvider extends AutocompleteProvider {
|
||||
constructor() {
|
||||
|
@ -124,30 +37,37 @@ export default class CommandProvider extends AutocompleteProvider {
|
|||
});
|
||||
}
|
||||
|
||||
async getCompletions(query: string, selection: SelectionRange) {
|
||||
let completions = [];
|
||||
if (!selection.beginning) return completions;
|
||||
async getCompletions(query: string, selection: SelectionRange, force?: boolean): Array<Completion> {
|
||||
const {command, range} = this.getCurrentCommand(query, selection);
|
||||
if (command) {
|
||||
let results;
|
||||
if (command[0] == '/') {
|
||||
results = COMMANDS;
|
||||
} else {
|
||||
results = this.matcher.match(command[0]);
|
||||
if (!command) return [];
|
||||
|
||||
let matches = [];
|
||||
// check if the full match differs from the first word (i.e. returns false if the command has args)
|
||||
if (command[0] !== command[1]) {
|
||||
// The input looks like a command with arguments, perform exact match
|
||||
const name = command[1].substr(1); // strip leading `/`
|
||||
if (CommandMap[name]) {
|
||||
matches = [CommandMap[name]];
|
||||
}
|
||||
} else {
|
||||
if (query === '/') {
|
||||
// If they have just entered `/` show everything
|
||||
matches = COMMANDS;
|
||||
} else {
|
||||
// otherwise fuzzy match against all of the fields
|
||||
matches = this.matcher.match(command[1]);
|
||||
}
|
||||
completions = results.map((result) => {
|
||||
return {
|
||||
completion: result.command + ' ',
|
||||
component: (<TextualCompletion
|
||||
title={result.command}
|
||||
subtitle={result.args}
|
||||
description={_t(result.description)}
|
||||
/>),
|
||||
range,
|
||||
};
|
||||
});
|
||||
}
|
||||
return completions;
|
||||
|
||||
return matches.map((result) => ({
|
||||
// If the command is the same as the one they entered, we don't want to discard their arguments
|
||||
completion: result.command === command[1] ? command[0] : (result.command + ' '),
|
||||
component: <TextualCompletion
|
||||
title={result.command}
|
||||
subtitle={result.args}
|
||||
description={_t(result.description)} />,
|
||||
range,
|
||||
}));
|
||||
}
|
||||
|
||||
getName() {
|
||||
|
|
111
src/autocomplete/CommunityProvider.js
Normal file
111
src/autocomplete/CommunityProvider.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
Copyright 2018 New Vector Ltd
|
||||
Copyright 2018 Michael Telatynski <7t3chguy@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { _t } from '../languageHandler';
|
||||
import AutocompleteProvider from './AutocompleteProvider';
|
||||
import MatrixClientPeg from '../MatrixClientPeg';
|
||||
import FuzzyMatcher from './FuzzyMatcher';
|
||||
import {PillCompletion} from './Components';
|
||||
import sdk from '../index';
|
||||
import _sortBy from 'lodash/sortBy';
|
||||
import {makeGroupPermalink} from "../matrix-to";
|
||||
import type {Completion, SelectionRange} from "./Autocompleter";
|
||||
import FlairStore from "../stores/FlairStore";
|
||||
|
||||
const COMMUNITY_REGEX = /\B\+\S*/g;
|
||||
|
||||
function score(query, space) {
|
||||
const index = space.indexOf(query);
|
||||
if (index === -1) {
|
||||
return Infinity;
|
||||
} else {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
export default class CommunityProvider extends AutocompleteProvider {
|
||||
constructor() {
|
||||
super(COMMUNITY_REGEX);
|
||||
this.matcher = new FuzzyMatcher([], {
|
||||
keys: ['groupId', 'name', 'shortDescription'],
|
||||
});
|
||||
}
|
||||
|
||||
async getCompletions(query: string, selection: SelectionRange, force?: boolean = false): Array<Completion> {
|
||||
const BaseAvatar = sdk.getComponent('views.avatars.BaseAvatar');
|
||||
|
||||
// Disable autocompletions when composing commands because of various issues
|
||||
// (see https://github.com/vector-im/riot-web/issues/4762)
|
||||
if (/^(\/join|\/leave)/.test(query)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const cli = MatrixClientPeg.get();
|
||||
let completions = [];
|
||||
const {command, range} = this.getCurrentCommand(query, selection, force);
|
||||
if (command) {
|
||||
const joinedGroups = cli.getGroups().filter(({myMembership}) => myMembership === 'join');
|
||||
|
||||
const groups = (await Promise.all(joinedGroups.map(async ({groupId}) => {
|
||||
try {
|
||||
return FlairStore.getGroupProfileCached(cli, groupId);
|
||||
} catch (e) { // if FlairStore failed, fall back to just groupId
|
||||
return Promise.resolve({
|
||||
name: '',
|
||||
groupId,
|
||||
avatarUrl: '',
|
||||
shortDescription: '',
|
||||
});
|
||||
}
|
||||
})));
|
||||
|
||||
this.matcher.setObjects(groups);
|
||||
|
||||
const matchedString = command[0];
|
||||
completions = this.matcher.match(matchedString);
|
||||
completions = _sortBy(completions, [
|
||||
(c) => score(matchedString, c.groupId),
|
||||
(c) => c.groupId.length,
|
||||
]).map(({avatarUrl, groupId, name}) => ({
|
||||
completion: groupId,
|
||||
suffix: ' ',
|
||||
href: makeGroupPermalink(groupId),
|
||||
component: (
|
||||
<PillCompletion initialComponent={
|
||||
<BaseAvatar name={name || groupId}
|
||||
width={24} height={24}
|
||||
url={avatarUrl ? cli.mxcUrlToHttp(avatarUrl, 24, 24) : null} />
|
||||
} title={name} description={groupId} />
|
||||
),
|
||||
range,
|
||||
}))
|
||||
.slice(0, 4);
|
||||
}
|
||||
return completions;
|
||||
}
|
||||
|
||||
getName() {
|
||||
return '💬 ' + _t('Communities');
|
||||
}
|
||||
|
||||
renderCompletions(completions: [React.Component]): ?React.Component {
|
||||
return <div className="mx_Autocomplete_Completion_container_pill mx_Autocomplete_Completion_container_truncate">
|
||||
{ completions }
|
||||
</div>;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Copyright 2016 Aviral Dasgupta
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
Copyright 2017, 2018 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -22,7 +22,7 @@ import AutocompleteProvider from './AutocompleteProvider';
|
|||
import 'whatwg-fetch';
|
||||
|
||||
import {TextualCompletion} from './Components';
|
||||
import type {SelectionRange} from './Autocompleter';
|
||||
import type {SelectionRange} from "./Autocompleter";
|
||||
|
||||
const DDG_REGEX = /\/ddg\s+(.+)$/g;
|
||||
const REFERRER = 'vector';
|
||||
|
@ -37,7 +37,7 @@ export default class DuckDuckGoProvider extends AutocompleteProvider {
|
|||
+ `&format=json&no_redirect=1&no_html=1&t=${encodeURIComponent(REFERRER)}`;
|
||||
}
|
||||
|
||||
async getCompletions(query: string, selection: SelectionRange) {
|
||||
async getCompletions(query: string, selection: SelectionRange, force?: boolean = false) {
|
||||
const {command, range} = this.getCurrentCommand(query, selection);
|
||||
if (!query || !command) {
|
||||
return [];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Copyright 2016 Aviral Dasgupta
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
Copyright 2017, 2018 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -19,11 +19,11 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import { _t } from '../languageHandler';
|
||||
import AutocompleteProvider from './AutocompleteProvider';
|
||||
import {emojioneList, shortnameToImage, shortnameToUnicode, asciiRegexp, unicodeRegexp} from 'emojione';
|
||||
import {shortnameToUnicode, asciiRegexp, unicodeRegexp} from 'emojione';
|
||||
import FuzzyMatcher from './FuzzyMatcher';
|
||||
import sdk from '../index';
|
||||
import {PillCompletion} from './Components';
|
||||
import type {SelectionRange, Completion} from './Autocompleter';
|
||||
import type {Completion, SelectionRange} from './Autocompleter';
|
||||
import _uniq from 'lodash/uniq';
|
||||
import _sortBy from 'lodash/sortBy';
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
|
@ -95,7 +95,7 @@ export default class EmojiProvider extends AutocompleteProvider {
|
|||
});
|
||||
}
|
||||
|
||||
async getCompletions(query: string, selection: SelectionRange) {
|
||||
async getCompletions(query: string, selection: SelectionRange, force?: boolean): Array<Completion> {
|
||||
if (SettingsStore.getValue("MessageComposerInput.dontSuggestEmoji")) {
|
||||
return []; // don't give any suggestions if the user doesn't want them
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import { _t } from '../languageHandler';
|
|||
import MatrixClientPeg from '../MatrixClientPeg';
|
||||
import {PillCompletion} from './Components';
|
||||
import sdk from '../index';
|
||||
import type {SelectionRange} from './Autocompleter';
|
||||
import type {Completion, SelectionRange} from "./Autocompleter";
|
||||
|
||||
const AT_ROOM_REGEX = /@\S*/g;
|
||||
|
||||
|
@ -30,7 +30,7 @@ export default class NotifProvider extends AutocompleteProvider {
|
|||
this.room = room;
|
||||
}
|
||||
|
||||
async getCompletions(query: string, selection: SelectionRange, force = false) {
|
||||
async getCompletions(query: string, selection: SelectionRange, force?:boolean = false): Array<Completion> {
|
||||
const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar');
|
||||
|
||||
const client = MatrixClientPeg.get();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//@flow
|
||||
/*
|
||||
Copyright 2017 Aviral Dasgupta
|
||||
Copyright 2018 Michael Telatynski <7t3chguy@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -27,6 +28,10 @@ class KeyMap {
|
|||
priorityMap = new Map();
|
||||
}
|
||||
|
||||
function stripDiacritics(str: string): string {
|
||||
return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
||||
}
|
||||
|
||||
export default class QueryMatcher {
|
||||
/**
|
||||
* @param {object[]} objects the objects to perform a match on
|
||||
|
@ -46,10 +51,11 @@ export default class QueryMatcher {
|
|||
objects.forEach((object, i) => {
|
||||
const keyValues = _at(object, keys);
|
||||
for (const keyValue of keyValues) {
|
||||
if (!map.hasOwnProperty(keyValue)) {
|
||||
map[keyValue] = [];
|
||||
const key = stripDiacritics(keyValue).toLowerCase();
|
||||
if (!map.hasOwnProperty(key)) {
|
||||
map[key] = [];
|
||||
}
|
||||
map[keyValue].push(object);
|
||||
map[key].push(object);
|
||||
}
|
||||
keyMap.priorityMap.set(object, i);
|
||||
});
|
||||
|
@ -82,7 +88,7 @@ export default class QueryMatcher {
|
|||
}
|
||||
|
||||
match(query: String): Array<Object> {
|
||||
query = query.toLowerCase();
|
||||
query = stripDiacritics(query).toLowerCase();
|
||||
if (this.options.shouldMatchWordsOnly) {
|
||||
query = query.replace(/[^\w]/g, '');
|
||||
}
|
||||
|
@ -91,7 +97,7 @@ export default class QueryMatcher {
|
|||
}
|
||||
const results = [];
|
||||
this.keyMap.keys.forEach((key) => {
|
||||
let resultKey = key.toLowerCase();
|
||||
let resultKey = key;
|
||||
if (this.options.shouldMatchWordsOnly) {
|
||||
resultKey = resultKey.replace(/[^\w]/g, '');
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
Copyright 2016 Aviral Dasgupta
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
Copyright 2017, 2018 New Vector Ltd
|
||||
Copyright 2018 Michael Telatynski <7t3chguy@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -26,9 +27,9 @@ import {getDisplayAliasForRoom} from '../Rooms';
|
|||
import sdk from '../index';
|
||||
import _sortBy from 'lodash/sortBy';
|
||||
import {makeRoomPermalink} from "../matrix-to";
|
||||
import type {SelectionRange} from './Autocompleter';
|
||||
import type {Completion, SelectionRange} from "./Autocompleter";
|
||||
|
||||
const ROOM_REGEX = /(?=#)(\S*)/g;
|
||||
const ROOM_REGEX = /\B#\S*/g;
|
||||
|
||||
function score(query, space) {
|
||||
const index = space.indexOf(query);
|
||||
|
@ -47,7 +48,7 @@ export default class RoomProvider extends AutocompleteProvider {
|
|||
});
|
||||
}
|
||||
|
||||
async getCompletions(query: string, selection: SelectionRange, force = false) {
|
||||
async getCompletions(query: string, selection: SelectionRange, force?: boolean = false): Array<Completion> {
|
||||
const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar');
|
||||
|
||||
const client = MatrixClientPeg.get();
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
Copyright 2016 Aviral Dasgupta
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
Copyright 2017, 2018 New Vector Ltd
|
||||
Copyright 2018 Michael Telatynski <7t3chguy@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -23,15 +24,14 @@ import AutocompleteProvider from './AutocompleteProvider';
|
|||
import {PillCompletion} from './Components';
|
||||
import sdk from '../index';
|
||||
import FuzzyMatcher from './FuzzyMatcher';
|
||||
import _pull from 'lodash/pull';
|
||||
import _sortBy from 'lodash/sortBy';
|
||||
import MatrixClientPeg from '../MatrixClientPeg';
|
||||
|
||||
import type {Room, RoomMember} from 'matrix-js-sdk';
|
||||
import type {SelectionRange} from './Autocompleter';
|
||||
import type {MatrixEvent, Room, RoomMember, RoomState} from 'matrix-js-sdk';
|
||||
import {makeUserPermalink} from "../matrix-to";
|
||||
import type {Completion, SelectionRange} from "./Autocompleter";
|
||||
|
||||
const USER_REGEX = /@\S*/g;
|
||||
const USER_REGEX = /\B@\S*/g;
|
||||
|
||||
// used when you hit 'tab' - we allow some separator chars at the beginning
|
||||
// to allow you to tab-complete /mat into /(matthew)
|
||||
|
@ -47,7 +47,7 @@ export default class UserProvider extends AutocompleteProvider {
|
|||
this.matcher = new FuzzyMatcher([], {
|
||||
keys: ['name', 'userId'],
|
||||
shouldMatchPrefix: true,
|
||||
shouldMatchWordsOnly: false
|
||||
shouldMatchWordsOnly: false,
|
||||
});
|
||||
|
||||
this._onRoomTimelineBound = this._onRoomTimeline.bind(this);
|
||||
|
@ -64,7 +64,7 @@ export default class UserProvider extends AutocompleteProvider {
|
|||
}
|
||||
}
|
||||
|
||||
_onRoomTimeline(ev, room, toStartOfTimeline, removed, data) {
|
||||
_onRoomTimeline(ev: MatrixEvent, room: Room, toStartOfTimeline: boolean, removed: boolean, data: Object) {
|
||||
if (!room) return;
|
||||
if (removed) return;
|
||||
if (room.roomId !== this.room.roomId) return;
|
||||
|
@ -80,7 +80,7 @@ export default class UserProvider extends AutocompleteProvider {
|
|||
this.onUserSpoke(ev.sender);
|
||||
}
|
||||
|
||||
_onRoomStateMember(ev, state, member) {
|
||||
_onRoomStateMember(ev: MatrixEvent, state: RoomState, member: RoomMember) {
|
||||
// ignore members in other rooms
|
||||
if (member.roomId !== this.room.roomId) {
|
||||
return;
|
||||
|
@ -90,7 +90,7 @@ export default class UserProvider extends AutocompleteProvider {
|
|||
this.users = null;
|
||||
}
|
||||
|
||||
async getCompletions(query: string, selection: SelectionRange, force = false) {
|
||||
async getCompletions(query: string, selection: SelectionRange, force?: boolean = false): Array<Completion> {
|
||||
const MemberAvatar = sdk.getComponent('views.avatars.MemberAvatar');
|
||||
|
||||
// lazy-load user list into matcher
|
||||
|
@ -126,7 +126,7 @@ export default class UserProvider extends AutocompleteProvider {
|
|||
return completions;
|
||||
}
|
||||
|
||||
getName() {
|
||||
getName(): string {
|
||||
return '👥 ' + _t('Users');
|
||||
}
|
||||
|
||||
|
@ -139,13 +139,9 @@ export default class UserProvider extends AutocompleteProvider {
|
|||
}
|
||||
|
||||
const currentUserId = MatrixClientPeg.get().credentials.userId;
|
||||
this.users = this.room.getJoinedMembers().filter((member) => {
|
||||
if (member.userId !== currentUserId) return true;
|
||||
});
|
||||
this.users = this.room.getJoinedMembers().filter(({userId}) => userId !== currentUserId);
|
||||
|
||||
this.users = _sortBy(this.users, (member) =>
|
||||
1E20 - lastSpoken[member.userId] || 1E20,
|
||||
);
|
||||
this.users = _sortBy(this.users, (member) => 1E20 - lastSpoken[member.userId] || 1E20);
|
||||
|
||||
this.matcher.setObjects(this.users);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue