Merge branch 'develop' into sort-imports

Signed-off-by: Aaron Raimist <aaron@raim.ist>
This commit is contained in:
Aaron Raimist 2021-12-09 08:34:20 +00:00
commit 7b94e13a84
642 changed files with 30052 additions and 8035 deletions

View file

@ -17,7 +17,7 @@ limitations under the License.
*/
import React from 'react';
import { TimelineRenderingType } from '../contexts/RoomContext';
import type { ICompletion, ISelectionRange } from './Autocompleter';
export interface ICommand {
@ -28,11 +28,19 @@ export interface ICommand {
};
}
export interface IAutocompleteOptions {
commandRegex?: RegExp;
forcedCommandRegex?: RegExp;
renderingType?: TimelineRenderingType;
}
export default abstract class AutocompleteProvider {
commandRegex: RegExp;
forcedCommandRegex: RegExp;
protected constructor(commandRegex?: RegExp, forcedCommandRegex?: RegExp) {
protected renderingType: TimelineRenderingType = TimelineRenderingType.Room;
protected constructor({ commandRegex, forcedCommandRegex, renderingType }: IAutocompleteOptions) {
if (commandRegex) {
if (!commandRegex.global) {
throw new Error('commandRegex must have global flag set');
@ -45,6 +53,9 @@ export default abstract class AutocompleteProvider {
}
this.forcedCommandRegex = forcedCommandRegex;
}
if (renderingType) {
this.renderingType = renderingType;
}
}
destroy() {

View file

@ -27,7 +27,8 @@ import NotifProvider from './NotifProvider';
import { timeout } from "../utils/promise";
import AutocompleteProvider, { ICommand } from "./AutocompleteProvider";
import SpaceProvider from "./SpaceProvider";
import SpaceStore from "../stores/SpaceStore";
import SpaceStore from "../stores/spaces/SpaceStore";
import { TimelineRenderingType } from '../contexts/RoomContext';
export interface ISelectionRange {
beginning?: boolean; // whether the selection is in the first block of the editor or not
@ -75,10 +76,10 @@ export default class Autocompleter {
room: Room;
providers: AutocompleteProvider[];
constructor(room: Room) {
constructor(room: Room, renderingType: TimelineRenderingType = TimelineRenderingType.Room) {
this.room = room;
this.providers = PROVIDERS.map((Prov) => {
return new Prov(room);
return new Prov(room, renderingType);
});
}

View file

@ -25,17 +25,20 @@ import QueryMatcher from './QueryMatcher';
import { TextualCompletion } from './Components';
import { ICompletion, ISelectionRange } from "./Autocompleter";
import { Command, Commands, CommandMap } from '../SlashCommands';
import { Room } from 'matrix-js-sdk/src/models/room';
import { TimelineRenderingType } from '../contexts/RoomContext';
const COMMAND_RE = /(^\/\w*)(?: .*)?/g;
export default class CommandProvider extends AutocompleteProvider {
matcher: QueryMatcher<Command>;
constructor() {
super(COMMAND_RE);
constructor(room: Room, renderingType?: TimelineRenderingType) {
super({ commandRegex: COMMAND_RE, renderingType });
this.matcher = new QueryMatcher(Commands, {
keys: ['command', 'args', 'description'],
funcs: [({ aliases }) => aliases.join(" ")], // aliases
context: renderingType,
});
}
@ -48,7 +51,7 @@ export default class CommandProvider extends AutocompleteProvider {
const { command, range } = this.getCurrentCommand(query, selection);
if (!command) return [];
let matches = [];
let matches: Command[] = [];
// 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
@ -69,7 +72,10 @@ export default class CommandProvider extends AutocompleteProvider {
}
}
return matches.filter(cmd => cmd.isEnabled()).map((result) => {
return matches.filter(cmd => {
const display = !cmd.renderingTypes || cmd.renderingTypes.includes(this.renderingType);
return cmd.isEnabled() && display;
}).map((result) => {
let completion = result.getCommand() + ' ';
const usedAlias = result.aliases.find(alias => `/${alias}` === command[1]);
// If the command (or an alias) is the same as the one they entered, we don't want to discard their arguments

View file

@ -29,6 +29,8 @@ import { ICompletion, ISelectionRange } from "./Autocompleter";
import FlairStore from "../stores/FlairStore";
import { mediaFromMxc } from "../customisations/Media";
import BaseAvatar from '../components/views/avatars/BaseAvatar';
import { Room } from 'matrix-js-sdk/src/models/room';
import { TimelineRenderingType } from '../contexts/RoomContext';
const COMMUNITY_REGEX = /\B\+\S*/g;
@ -44,8 +46,8 @@ function score(query, space) {
export default class CommunityProvider extends AutocompleteProvider {
matcher: QueryMatcher<Group>;
constructor() {
super(COMMUNITY_REGEX);
constructor(room: Room, renderingType?: TimelineRenderingType) {
super({ commandRegex: COMMUNITY_REGEX, renderingType });
this.matcher = new QueryMatcher([], {
keys: ['groupId', 'name', 'shortDescription'],
});

View file

@ -18,17 +18,19 @@ limitations under the License.
*/
import React from 'react';
import { uniq, sortBy } from 'lodash';
import EMOTICON_REGEX from 'emojibase-regex/emoticon';
import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider';
import QueryMatcher from './QueryMatcher';
import { PillCompletion } from './Components';
import { ICompletion, ISelectionRange } from './Autocompleter';
import { uniq, sortBy } from 'lodash';
import SettingsStore from "../settings/SettingsStore";
import { EMOJI, IEmoji } from '../emoji';
import EMOTICON_REGEX from 'emojibase-regex/emoticon';
import { Room } from 'matrix-js-sdk/src/models/room';
import { TimelineRenderingType } from '../contexts/RoomContext';
const LIMIT = 20;
// Match for ascii-style ";-)" emoticons or ":wink:" shortcodes provided by emojibase
@ -64,8 +66,8 @@ export default class EmojiProvider extends AutocompleteProvider {
matcher: QueryMatcher<ISortedEmoji>;
nameMatcher: QueryMatcher<ISortedEmoji>;
constructor() {
super(EMOJI_REGEX);
constructor(room: Room, renderingType?: TimelineRenderingType) {
super({ commandRegex: EMOJI_REGEX, renderingType });
this.matcher = new QueryMatcher<ISortedEmoji>(SORTED_EMOJI, {
keys: [],
funcs: [o => o.emoji.shortcodes.map(s => `:${s}:`)],

View file

@ -23,15 +23,13 @@ import { MatrixClientPeg } from '../MatrixClientPeg';
import { PillCompletion } from './Components';
import { ICompletion, ISelectionRange } from "./Autocompleter";
import RoomAvatar from '../components/views/avatars/RoomAvatar';
import { TimelineRenderingType } from '../contexts/RoomContext';
const AT_ROOM_REGEX = /@\S*/g;
export default class NotifProvider extends AutocompleteProvider {
room: Room;
constructor(room) {
super(AT_ROOM_REGEX);
this.room = room;
constructor(public room: Room, renderingType?: TimelineRenderingType) {
super({ commandRegex: AT_ROOM_REGEX, renderingType });
}
async getCompletions(

View file

@ -18,6 +18,7 @@ limitations under the License.
import { at, uniq } from 'lodash';
import { removeHiddenChars } from "matrix-js-sdk/src/utils";
import { TimelineRenderingType } from '../contexts/RoomContext';
interface IOptions<T extends {}> {
keys: Array<string | keyof T>;
@ -25,6 +26,7 @@ interface IOptions<T extends {}> {
shouldMatchWordsOnly?: boolean;
// whether to apply unhomoglyph and strip diacritics to fuzz up the search. Defaults to true
fuzzy?: boolean;
context?: TimelineRenderingType;
}
/**

View file

@ -28,7 +28,8 @@ import { PillCompletion } from './Components';
import { makeRoomPermalink } from "../utils/permalinks/Permalinks";
import { ICompletion, ISelectionRange } from "./Autocompleter";
import RoomAvatar from '../components/views/avatars/RoomAvatar';
import SpaceStore from "../stores/SpaceStore";
import SpaceStore from "../stores/spaces/SpaceStore";
import { TimelineRenderingType } from "../contexts/RoomContext";
const ROOM_REGEX = /\B#\S*/g;
@ -48,8 +49,8 @@ function matcherObject(room: Room, displayedAlias: string, matchName = "") {
export default class RoomProvider extends AutocompleteProvider {
protected matcher: QueryMatcher<Room>;
constructor() {
super(ROOM_REGEX);
constructor(room: Room, renderingType?: TimelineRenderingType) {
super({ commandRegex: ROOM_REGEX, renderingType });
this.matcher = new QueryMatcher([], {
keys: ['displayedAlias', 'matchName'],
});

View file

@ -33,6 +33,7 @@ import { _t } from '../languageHandler';
import { makeUserPermalink } from "../utils/permalinks/Permalinks";
import { ICompletion, ISelectionRange } from "./Autocompleter";
import MemberAvatar from '../components/views/avatars/MemberAvatar';
import { TimelineRenderingType } from '../contexts/RoomContext';
const USER_REGEX = /\B@\S*/g;
@ -50,8 +51,12 @@ export default class UserProvider extends AutocompleteProvider {
users: RoomMember[];
room: Room;
constructor(room: Room) {
super(USER_REGEX, FORCED_USER_REGEX);
constructor(room: Room, renderingType?: TimelineRenderingType) {
super({
commandRegex: USER_REGEX,
forcedCommandRegex: FORCED_USER_REGEX,
renderingType,
});
this.room = room;
this.matcher = new QueryMatcher([], {
keys: ['name'],