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

Commit da7d31a

Browse files
authored
Merge pull request #5686 from robintown/reply-commands
Support replying with a message command
2 parents 8587ec8 + 5636204 commit da7d31a

File tree

2 files changed

+47
-25
lines changed

2 files changed

+47
-25
lines changed

src/SlashCommands.tsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ limitations under the License.
2020

2121
import * as React from 'react';
2222

23+
import { ContentHelpers } from 'matrix-js-sdk';
2324
import {MatrixClientPeg} from './MatrixClientPeg';
2425
import dis from './dispatcher/dispatcher';
2526
import * as sdk from './index';
@@ -126,10 +127,10 @@ export class Command {
126127
return this.getCommand() + " " + this.args;
127128
}
128129

129-
run(roomId: string, args: string, cmd: string) {
130+
run(roomId: string, args: string) {
130131
// if it has no runFn then its an ignored/nop command (autocomplete only) e.g `/me`
131132
if (!this.runFn) return reject(_t("Command error"));
132-
return this.runFn.bind(this)(roomId, args, cmd);
133+
return this.runFn.bind(this)(roomId, args);
133134
}
134135

135136
getUsage() {
@@ -163,7 +164,7 @@ export const Commands = [
163164
if (args) {
164165
message = message + ' ' + args;
165166
}
166-
return success(MatrixClientPeg.get().sendTextMessage(roomId, message));
167+
return success(ContentHelpers.makeTextMessage(message));
167168
},
168169
category: CommandCategories.messages,
169170
}),
@@ -176,7 +177,7 @@ export const Commands = [
176177
if (args) {
177178
message = message + ' ' + args;
178179
}
179-
return success(MatrixClientPeg.get().sendTextMessage(roomId, message));
180+
return success(ContentHelpers.makeTextMessage(message));
180181
},
181182
category: CommandCategories.messages,
182183
}),
@@ -189,7 +190,7 @@ export const Commands = [
189190
if (args) {
190191
message = message + ' ' + args;
191192
}
192-
return success(MatrixClientPeg.get().sendTextMessage(roomId, message));
193+
return success(ContentHelpers.makeTextMessage(message));
193194
},
194195
category: CommandCategories.messages,
195196
}),
@@ -202,7 +203,7 @@ export const Commands = [
202203
if (args) {
203204
message = message + ' ' + args;
204205
}
205-
return success(MatrixClientPeg.get().sendTextMessage(roomId, message));
206+
return success(ContentHelpers.makeTextMessage(message));
206207
},
207208
category: CommandCategories.messages,
208209
}),
@@ -211,7 +212,7 @@ export const Commands = [
211212
args: '<message>',
212213
description: _td('Sends a message as plain text, without interpreting it as markdown'),
213214
runFn: function(roomId, messages) {
214-
return success(MatrixClientPeg.get().sendTextMessage(roomId, messages));
215+
return success(ContentHelpers.makeTextMessage(messages));
215216
},
216217
category: CommandCategories.messages,
217218
}),
@@ -220,7 +221,7 @@ export const Commands = [
220221
args: '<message>',
221222
description: _td('Sends a message as html, without interpreting it as markdown'),
222223
runFn: function(roomId, messages) {
223-
return success(MatrixClientPeg.get().sendHtmlMessage(roomId, messages, messages));
224+
return success(ContentHelpers.makeHtmlMessage(messages, messages));
224225
},
225226
category: CommandCategories.messages,
226227
}),
@@ -965,7 +966,7 @@ export const Commands = [
965966
args: '<message>',
966967
runFn: function(roomId, args) {
967968
if (!args) return reject(this.getUserId());
968-
return success(MatrixClientPeg.get().sendHtmlMessage(roomId, args, textToHtmlRainbow(args)));
969+
return success(ContentHelpers.makeHtmlMessage(args, textToHtmlRainbow(args)));
969970
},
970971
category: CommandCategories.messages,
971972
}),
@@ -975,7 +976,7 @@ export const Commands = [
975976
args: '<message>',
976977
runFn: function(roomId, args) {
977978
if (!args) return reject(this.getUserId());
978-
return success(MatrixClientPeg.get().sendHtmlEmote(roomId, args, textToHtmlRainbow(args)));
979+
return success(ContentHelpers.makeHtmlEmote(args, textToHtmlRainbow(args)));
979980
},
980981
category: CommandCategories.messages,
981982
}),
@@ -1200,10 +1201,13 @@ export function parseCommandString(input: string) {
12001201
* processing the command, or 'promise' if a request was sent out.
12011202
* Returns null if the input didn't match a command.
12021203
*/
1203-
export function getCommand(roomId: string, input: string) {
1204+
export function getCommand(input: string) {
12041205
const {cmd, args} = parseCommandString(input);
12051206

12061207
if (CommandMap.has(cmd) && CommandMap.get(cmd).isEnabled()) {
1207-
return () => CommandMap.get(cmd).run(roomId, args, cmd);
1208+
return {
1209+
cmd: CommandMap.get(cmd),
1210+
args,
1211+
};
12081212
}
12091213
}

src/components/views/rooms/SendMessageComposer.js

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import ReplyThread from "../elements/ReplyThread";
3333
import {parseEvent} from '../../../editor/deserialize';
3434
import {findEditableEvent} from '../../../utils/EventUtils';
3535
import SendHistoryManager from "../../../SendHistoryManager";
36-
import {getCommand} from '../../../SlashCommands';
36+
import {CommandCategories, getCommand} from '../../../SlashCommands';
3737
import * as sdk from '../../../index';
3838
import Modal from '../../../Modal';
3939
import {_t, _td} from '../../../languageHandler';
@@ -291,15 +291,22 @@ export default class SendMessageComposer extends React.Component {
291291
}
292292
return text + part.text;
293293
}, "");
294-
return [getCommand(this.props.room.roomId, commandText), commandText];
294+
const {cmd, args} = getCommand(commandText);
295+
return [cmd, args, commandText];
295296
}
296297

297-
async _runSlashCommand(fn) {
298-
const cmd = fn();
299-
let error = cmd.error;
300-
if (cmd.promise) {
298+
async _runSlashCommand(cmd, args) {
299+
const result = cmd.run(this.props.room.roomId, args);
300+
let messageContent;
301+
let error = result.error;
302+
if (result.promise) {
301303
try {
302-
await cmd.promise;
304+
if (cmd.category === CommandCategories.messages) {
305+
// The command returns a modified message that we need to pass on
306+
messageContent = await result.promise;
307+
} else {
308+
await result.promise;
309+
}
303310
} catch (err) {
304311
error = err;
305312
}
@@ -308,7 +315,7 @@ export default class SendMessageComposer extends React.Component {
308315
console.error("Command failure: %s", error);
309316
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
310317
// assume the error is a server error when the command is async
311-
const isServerError = !!cmd.promise;
318+
const isServerError = !!result.promise;
312319
const title = isServerError ? _td("Server error") : _td("Command error");
313320

314321
let errText;
@@ -326,6 +333,7 @@ export default class SendMessageComposer extends React.Component {
326333
});
327334
} else {
328335
console.log("Command success.");
336+
if (messageContent) return messageContent;
329337
}
330338
}
331339

@@ -334,13 +342,22 @@ export default class SendMessageComposer extends React.Component {
334342
return;
335343
}
336344

345+
const replyToEvent = this.props.replyToEvent;
337346
let shouldSend = true;
347+
let content;
338348

339349
if (!containsEmote(this.model) && this._isSlashCommand()) {
340-
const [cmd, commandText] = this._getSlashCommand();
350+
const [cmd, args, commandText] = this._getSlashCommand();
341351
if (cmd) {
342-
shouldSend = false;
343-
this._runSlashCommand(cmd);
352+
if (cmd.category === CommandCategories.messages) {
353+
content = await this._runSlashCommand(cmd, args);
354+
if (replyToEvent) {
355+
addReplyToMessageContent(content, replyToEvent, this.props.permalinkCreator);
356+
}
357+
} else {
358+
this._runSlashCommand(cmd, args);
359+
shouldSend = false;
360+
}
344361
} else {
345362
// ask the user if their unknown command should be sent as a message
346363
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
@@ -375,11 +392,12 @@ export default class SendMessageComposer extends React.Component {
375392
this._sendQuickReaction();
376393
}
377394

378-
const replyToEvent = this.props.replyToEvent;
379395
if (shouldSend) {
380396
const startTime = CountlyAnalytics.getTimestamp();
381397
const {roomId} = this.props.room;
382-
const content = createMessageContent(this.model, this.props.permalinkCreator, replyToEvent);
398+
if (!content) {
399+
content = createMessageContent(this.model, this.props.permalinkCreator, replyToEvent);
400+
}
383401
// don't bother sending an empty message
384402
if (!content.body.trim()) return;
385403

0 commit comments

Comments
 (0)