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

Commit

Permalink
Fix slash commands not being enabled in certain cases (#11090)
Browse files Browse the repository at this point in the history
* Fix slash commands not being enabled in certain cases

* Fix import cycle
  • Loading branch information
t3chguy authored Jun 14, 2023
1 parent 9c48487 commit 6486255
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 10 deletions.
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

0 comments on commit 6486255

Please sign in to comment.