Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Fix slash commands not being enabled in certain cases #11090

Merged
merged 2 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/SlashCommands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import { htmlSerializeFromMdIfNeeded } from "./editor/serialize";
import { leaveRoomBehaviour } from "./utils/leave-behaviour";
import { isLocalRoom } from "./utils/localRoom/isLocalRoom";
import { SdkContextClass } from "./contexts/SDKContext";
import { MatrixClientPeg } from "./MatrixClientPeg";

// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
interface HTMLInputEvent extends Event {
Expand Down Expand Up @@ -122,7 +123,7 @@ interface ICommandOpts {
runFn?: RunFn;
category: string;
hideCompletionAfterSpace?: boolean;
isEnabled?(matrixClient?: MatrixClient): boolean;
isEnabled?(matrixClient: MatrixClient | null): boolean;
renderingTypes?: TimelineRenderingType[];
}

Expand All @@ -136,7 +137,7 @@ export class Command {
public readonly hideCompletionAfterSpace: boolean;
public readonly renderingTypes?: TimelineRenderingType[];
public readonly analyticsName?: SlashCommandEvent["command"];
private readonly _isEnabled?: (matrixClient?: MatrixClient) => boolean;
private readonly _isEnabled?: (matrixClient: MatrixClient | null) => boolean;

public constructor(opts: ICommandOpts) {
this.command = opts.command;
Expand Down Expand Up @@ -189,7 +190,7 @@ export class Command {
return _t("Usage") + ": " + this.getCommandWithArgs();
}

public isEnabled(cli?: MatrixClient): boolean {
public isEnabled(cli: MatrixClient | null): boolean {
return this._isEnabled?.(cli) ?? true;
}
}
Expand All @@ -206,15 +207,15 @@ function successSync(value: any): RunResult {
return success(Promise.resolve(value));
}

const isCurrentLocalRoom = (cli?: MatrixClient): boolean => {
const isCurrentLocalRoom = (cli: MatrixClient | null): boolean => {
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
if (!roomId) return false;
const room = cli?.getRoom(roomId);
if (!room) return false;
return isLocalRoom(room);
};

const canAffectPowerlevels = (cli?: MatrixClient): boolean => {
const canAffectPowerlevels = (cli: MatrixClient | null): boolean => {
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
if (!cli || !roomId) return false;
const room = cli?.getRoom(roomId);
Expand Down Expand Up @@ -1425,7 +1426,7 @@ interface ICmd {
export function getCommand(input: string): ICmd {
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 {
cmd: CommandMap.get(cmd),
args,
Expand Down
7 changes: 5 additions & 2 deletions src/autocomplete/CommandProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { TextualCompletion } from "./Components";
import { ICompletion, ISelectionRange } from "./Autocompleter";
import { Command, Commands, CommandMap } from "../SlashCommands";
import { TimelineRenderingType } from "../contexts/RoomContext";
import { MatrixClientPeg } from "../MatrixClientPeg";

const COMMAND_RE = /(^\/\w*)(?: .*)?/g;

Expand All @@ -51,12 +52,14 @@ export default class CommandProvider extends AutocompleteProvider {
const { command, range } = this.getCurrentCommand(query, selection);
if (!command) return [];

const cli = MatrixClientPeg.get();

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
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
if (CommandMap.get(name)!.hideCompletionAfterSpace) return [];
matches = [CommandMap.get(name)!];
Expand All @@ -75,7 +78,7 @@ export default class CommandProvider extends AutocompleteProvider {
return matches
.filter((cmd) => {
const display = !cmd.renderingTypes || cmd.renderingTypes.includes(this.renderingType);
return cmd.isEnabled() && display;
return cmd.isEnabled(cli) && display;
})
.map((result) => {
let completion = result.getCommand() + " ";
Expand Down
3 changes: 2 additions & 1 deletion src/components/views/dialogs/SlashCommandHelpDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import React from "react";
import { _t } from "../../../languageHandler";
import { Command, CommandCategories, Commands } from "../../../SlashCommands";
import InfoDialog from "./InfoDialog";
import { MatrixClientPeg } from "../../../MatrixClientPeg";

interface IProps {
onFinished(): void;
Expand All @@ -27,7 +28,7 @@ interface IProps {
const SlashCommandHelpDialog: React.FC<IProps> = ({ onFinished }) => {
const categories: Record<string, Command[]> = {};
Commands.forEach((cmd) => {
if (!cmd.isEnabled()) return;
if (!cmd.isEnabled(MatrixClientPeg.get())) return;
if (!categories[cmd.category]) {
categories[cmd.category] = [];
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/views/rooms/BasicMessageComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { ALTERNATE_KEY_NAME, KeyBindingAction } from "../../../accessibility/Key
import { _t } from "../../../languageHandler";
import { linkify } from "../../../linkify-matrix";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { MatrixClientPeg } from "../../../MatrixClientPeg";

// matches emoticons which follow the start of a line or whitespace
const REGEX_EMOTICON_WHITESPACE = new RegExp("(?:^|\\s)(" + EMOTICON_REGEX.source + ")\\s|:^$");
Expand Down Expand Up @@ -268,7 +269,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
if (isTyping && this.props.model.parts[0].type === "command") {
const { cmd } = parseCommandString(this.props.model.parts[0].text);
const command = CommandMap.get(cmd!);
if (!command?.isEnabled() || command.category !== CommandCategories.messages) {
if (!command?.isEnabled(MatrixClientPeg.get()) || command.category !== CommandCategories.messages) {
isTyping = false;
}
}
Expand Down