Fix slash commands not being enabled in certain cases (#11090)
* Fix slash commands not being enabled in certain cases * Fix import cycle
This commit is contained in:
parent
9c48487d85
commit
6486255f54
4 changed files with 16 additions and 10 deletions
|
@ -69,6 +69,7 @@ import { htmlSerializeFromMdIfNeeded } from "./editor/serialize";
|
||||||
import { leaveRoomBehaviour } from "./utils/leave-behaviour";
|
import { leaveRoomBehaviour } from "./utils/leave-behaviour";
|
||||||
import { isLocalRoom } from "./utils/localRoom/isLocalRoom";
|
import { isLocalRoom } from "./utils/localRoom/isLocalRoom";
|
||||||
import { SdkContextClass } from "./contexts/SDKContext";
|
import { SdkContextClass } from "./contexts/SDKContext";
|
||||||
|
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||||
|
|
||||||
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
|
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
|
||||||
interface HTMLInputEvent extends Event {
|
interface HTMLInputEvent extends Event {
|
||||||
|
@ -122,7 +123,7 @@ interface ICommandOpts {
|
||||||
runFn?: RunFn;
|
runFn?: RunFn;
|
||||||
category: string;
|
category: string;
|
||||||
hideCompletionAfterSpace?: boolean;
|
hideCompletionAfterSpace?: boolean;
|
||||||
isEnabled?(matrixClient?: MatrixClient): boolean;
|
isEnabled?(matrixClient: MatrixClient | null): boolean;
|
||||||
renderingTypes?: TimelineRenderingType[];
|
renderingTypes?: TimelineRenderingType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +137,7 @@ export class Command {
|
||||||
public readonly hideCompletionAfterSpace: boolean;
|
public readonly hideCompletionAfterSpace: boolean;
|
||||||
public readonly renderingTypes?: TimelineRenderingType[];
|
public readonly renderingTypes?: TimelineRenderingType[];
|
||||||
public readonly analyticsName?: SlashCommandEvent["command"];
|
public readonly analyticsName?: SlashCommandEvent["command"];
|
||||||
private readonly _isEnabled?: (matrixClient?: MatrixClient) => boolean;
|
private readonly _isEnabled?: (matrixClient: MatrixClient | null) => boolean;
|
||||||
|
|
||||||
public constructor(opts: ICommandOpts) {
|
public constructor(opts: ICommandOpts) {
|
||||||
this.command = opts.command;
|
this.command = opts.command;
|
||||||
|
@ -189,7 +190,7 @@ export class Command {
|
||||||
return _t("Usage") + ": " + this.getCommandWithArgs();
|
return _t("Usage") + ": " + this.getCommandWithArgs();
|
||||||
}
|
}
|
||||||
|
|
||||||
public isEnabled(cli?: MatrixClient): boolean {
|
public isEnabled(cli: MatrixClient | null): boolean {
|
||||||
return this._isEnabled?.(cli) ?? true;
|
return this._isEnabled?.(cli) ?? true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,7 +207,7 @@ function successSync(value: any): RunResult {
|
||||||
return success(Promise.resolve(value));
|
return success(Promise.resolve(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
const isCurrentLocalRoom = (cli?: MatrixClient): boolean => {
|
const isCurrentLocalRoom = (cli: MatrixClient | null): boolean => {
|
||||||
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||||
if (!roomId) return false;
|
if (!roomId) return false;
|
||||||
const room = cli?.getRoom(roomId);
|
const room = cli?.getRoom(roomId);
|
||||||
|
@ -214,7 +215,7 @@ const isCurrentLocalRoom = (cli?: MatrixClient): boolean => {
|
||||||
return isLocalRoom(room);
|
return isLocalRoom(room);
|
||||||
};
|
};
|
||||||
|
|
||||||
const canAffectPowerlevels = (cli?: MatrixClient): boolean => {
|
const canAffectPowerlevels = (cli: MatrixClient | null): boolean => {
|
||||||
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||||
if (!cli || !roomId) return false;
|
if (!cli || !roomId) return false;
|
||||||
const room = cli?.getRoom(roomId);
|
const room = cli?.getRoom(roomId);
|
||||||
|
@ -1425,7 +1426,7 @@ interface ICmd {
|
||||||
export function getCommand(input: string): ICmd {
|
export function getCommand(input: string): ICmd {
|
||||||
const { cmd, args } = parseCommandString(input);
|
const { cmd, args } = parseCommandString(input);
|
||||||
|
|
||||||
if (cmd && CommandMap.has(cmd) && CommandMap.get(cmd)!.isEnabled()) {
|
if (cmd && CommandMap.has(cmd) && CommandMap.get(cmd)!.isEnabled(MatrixClientPeg.get())) {
|
||||||
return {
|
return {
|
||||||
cmd: CommandMap.get(cmd),
|
cmd: CommandMap.get(cmd),
|
||||||
args,
|
args,
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { TextualCompletion } from "./Components";
|
||||||
import { ICompletion, ISelectionRange } from "./Autocompleter";
|
import { ICompletion, ISelectionRange } from "./Autocompleter";
|
||||||
import { Command, Commands, CommandMap } from "../SlashCommands";
|
import { Command, Commands, CommandMap } from "../SlashCommands";
|
||||||
import { TimelineRenderingType } from "../contexts/RoomContext";
|
import { TimelineRenderingType } from "../contexts/RoomContext";
|
||||||
|
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||||
|
|
||||||
const COMMAND_RE = /(^\/\w*)(?: .*)?/g;
|
const COMMAND_RE = /(^\/\w*)(?: .*)?/g;
|
||||||
|
|
||||||
|
@ -51,12 +52,14 @@ export default class CommandProvider extends AutocompleteProvider {
|
||||||
const { command, range } = this.getCurrentCommand(query, selection);
|
const { command, range } = this.getCurrentCommand(query, selection);
|
||||||
if (!command) return [];
|
if (!command) return [];
|
||||||
|
|
||||||
|
const cli = MatrixClientPeg.get();
|
||||||
|
|
||||||
let matches: Command[] = [];
|
let matches: Command[] = [];
|
||||||
// check if the full match differs from the first word (i.e. returns false if the command has args)
|
// check if the full match differs from the first word (i.e. returns false if the command has args)
|
||||||
if (command[0] !== command[1]) {
|
if (command[0] !== command[1]) {
|
||||||
// The input looks like a command with arguments, perform exact match
|
// The input looks like a command with arguments, perform exact match
|
||||||
const name = command[1].slice(1); // strip leading `/`
|
const name = command[1].slice(1); // strip leading `/`
|
||||||
if (CommandMap.has(name) && CommandMap.get(name)!.isEnabled()) {
|
if (CommandMap.has(name) && CommandMap.get(name)!.isEnabled(cli)) {
|
||||||
// some commands, namely `me` don't suit having the usage shown whilst typing their arguments
|
// some commands, namely `me` don't suit having the usage shown whilst typing their arguments
|
||||||
if (CommandMap.get(name)!.hideCompletionAfterSpace) return [];
|
if (CommandMap.get(name)!.hideCompletionAfterSpace) return [];
|
||||||
matches = [CommandMap.get(name)!];
|
matches = [CommandMap.get(name)!];
|
||||||
|
@ -75,7 +78,7 @@ export default class CommandProvider extends AutocompleteProvider {
|
||||||
return matches
|
return matches
|
||||||
.filter((cmd) => {
|
.filter((cmd) => {
|
||||||
const display = !cmd.renderingTypes || cmd.renderingTypes.includes(this.renderingType);
|
const display = !cmd.renderingTypes || cmd.renderingTypes.includes(this.renderingType);
|
||||||
return cmd.isEnabled() && display;
|
return cmd.isEnabled(cli) && display;
|
||||||
})
|
})
|
||||||
.map((result) => {
|
.map((result) => {
|
||||||
let completion = result.getCommand() + " ";
|
let completion = result.getCommand() + " ";
|
||||||
|
|
|
@ -19,6 +19,7 @@ import React from "react";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import { Command, CommandCategories, Commands } from "../../../SlashCommands";
|
import { Command, CommandCategories, Commands } from "../../../SlashCommands";
|
||||||
import InfoDialog from "./InfoDialog";
|
import InfoDialog from "./InfoDialog";
|
||||||
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
onFinished(): void;
|
onFinished(): void;
|
||||||
|
@ -27,7 +28,7 @@ interface IProps {
|
||||||
const SlashCommandHelpDialog: React.FC<IProps> = ({ onFinished }) => {
|
const SlashCommandHelpDialog: React.FC<IProps> = ({ onFinished }) => {
|
||||||
const categories: Record<string, Command[]> = {};
|
const categories: Record<string, Command[]> = {};
|
||||||
Commands.forEach((cmd) => {
|
Commands.forEach((cmd) => {
|
||||||
if (!cmd.isEnabled()) return;
|
if (!cmd.isEnabled(MatrixClientPeg.get())) return;
|
||||||
if (!categories[cmd.category]) {
|
if (!categories[cmd.category]) {
|
||||||
categories[cmd.category] = [];
|
categories[cmd.category] = [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ import { ALTERNATE_KEY_NAME, KeyBindingAction } from "../../../accessibility/Key
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import { linkify } from "../../../linkify-matrix";
|
import { linkify } from "../../../linkify-matrix";
|
||||||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
import { SdkContextClass } from "../../../contexts/SDKContext";
|
||||||
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
|
|
||||||
// matches emoticons which follow the start of a line or whitespace
|
// matches emoticons which follow the start of a line or whitespace
|
||||||
const REGEX_EMOTICON_WHITESPACE = new RegExp("(?:^|\\s)(" + EMOTICON_REGEX.source + ")\\s|:^$");
|
const REGEX_EMOTICON_WHITESPACE = new RegExp("(?:^|\\s)(" + EMOTICON_REGEX.source + ")\\s|:^$");
|
||||||
|
@ -268,7 +269,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
|
||||||
if (isTyping && this.props.model.parts[0].type === "command") {
|
if (isTyping && this.props.model.parts[0].type === "command") {
|
||||||
const { cmd } = parseCommandString(this.props.model.parts[0].text);
|
const { cmd } = parseCommandString(this.props.model.parts[0].text);
|
||||||
const command = CommandMap.get(cmd!);
|
const command = CommandMap.get(cmd!);
|
||||||
if (!command?.isEnabled() || command.category !== CommandCategories.messages) {
|
if (!command?.isEnabled(MatrixClientPeg.get()) || command.category !== CommandCategories.messages) {
|
||||||
isTyping = false;
|
isTyping = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue