insert command completion as command part (instead of plain)

this prevents the command being sent as plain text

this adds a `type` property to completions to decide which
parts should be inserted into the composer, hence deciding how
they will be rendered.
This commit is contained in:
Bruno Windels 2019-09-23 14:39:19 +02:00
parent 133e68191a
commit 228905bec2
7 changed files with 25 additions and 13 deletions

View file

@ -64,6 +64,7 @@ export default class CommandProvider extends AutocompleteProvider {
return matches.map((result) => ({ return matches.map((result) => ({
// If the command is the same as the one they entered, we don't want to discard their arguments // If the command is the same as the one they entered, we don't want to discard their arguments
completion: result.command === command[1] ? command[0] : (result.command + ' '), completion: result.command === command[1] ? command[0] : (result.command + ' '),
type: "command",
component: <TextualCompletion component: <TextualCompletion
title={result.command} title={result.command}
subtitle={result.args} subtitle={result.args}

View file

@ -84,6 +84,7 @@ export default class CommunityProvider extends AutocompleteProvider {
]).map(({avatarUrl, groupId, name}) => ({ ]).map(({avatarUrl, groupId, name}) => ({
completion: groupId, completion: groupId,
suffix: ' ', suffix: ' ',
type: "community",
href: makeGroupPermalink(groupId), href: makeGroupPermalink(groupId),
component: ( component: (
<PillCompletion initialComponent={ <PillCompletion initialComponent={

View file

@ -42,6 +42,7 @@ export default class NotifProvider extends AutocompleteProvider {
return [{ return [{
completion: '@room', completion: '@room',
completionId: '@room', completionId: '@room',
type: "at-room",
suffix: ' ', suffix: ' ',
component: ( component: (
<PillCompletion initialComponent={<RoomAvatar width={24} height={24} room={this.room} />} title="@room" description={_t("Notify the whole room")} /> <PillCompletion initialComponent={<RoomAvatar width={24} height={24} room={this.room} />} title="@room" description={_t("Notify the whole room")} />

View file

@ -89,6 +89,7 @@ export default class RoomProvider extends AutocompleteProvider {
return { return {
completion: displayAlias, completion: displayAlias,
completionId: displayAlias, completionId: displayAlias,
type: "room",
suffix: ' ', suffix: ' ',
href: makeRoomPermalink(displayAlias), href: makeRoomPermalink(displayAlias),
component: ( component: (

View file

@ -114,6 +114,7 @@ export default class UserProvider extends AutocompleteProvider {
// relies on the length of the entity === length of the text in the decoration. // relies on the length of the entity === length of the text in the decoration.
completion: user.rawDisplayName, completion: user.rawDisplayName,
completionId: user.userId, completionId: user.userId,
type: "user",
suffix: (selection.beginning && range.start === 0) ? ': ' : ' ', suffix: (selection.beginning && range.start === 0) ? ': ' : ' ',
href: makeUserPermalink(user.userId), href: makeUserPermalink(user.userId),
component: ( component: (

View file

@ -100,19 +100,21 @@ export default class AutocompleteWrapperModel {
_partForCompletion(completion) { _partForCompletion(completion) {
const {completionId} = completion; const {completionId} = completion;
const text = completion.completion; const text = completion.completion;
const firstChr = completionId && completionId[0]; switch (completion.type) {
switch (firstChr) { case "room":
case "@": {
if (completionId === "@room") {
return [this._partCreator.atRoomPill(completionId)];
} else {
return this._partCreator.createMentionParts(this._partIndex, text, completionId);
}
}
case "#":
return [this._partCreator.roomPill(completionId)]; return [this._partCreator.roomPill(completionId)];
// used for emoji and command completion replacement case "at-room":
return [this._partCreator.atRoomPill(completionId)];
case "user":
// not using suffix here, because we also need to calculate
// the suffix when clicking a display name to insert a mention,
// which happens in createMentionParts
return this._partCreator.createMentionParts(this._partIndex, text, completionId);
case "command":
// command needs special handling for auto complete, but also renders as plain texts
return [this._partCreator.command(text)];
default: default:
// used for emoji and other plain text completion replacement
return [this._partCreator.plain(text)]; return [this._partCreator.plain(text)];
} }
} }

View file

@ -456,15 +456,20 @@ export class CommandPartCreator extends PartCreator {
createPartForInput(text, partIndex) { createPartForInput(text, partIndex) {
// at beginning and starts with /? create // at beginning and starts with /? create
if (partIndex === 0 && text[0] === "/") { if (partIndex === 0 && text[0] === "/") {
return new CommandPart("", this._autoCompleteCreator); // text will be inserted by model, so pass empty string
return this.command("");
} else { } else {
return super.createPartForInput(text, partIndex); return super.createPartForInput(text, partIndex);
} }
} }
command(text) {
return new CommandPart(text, this._autoCompleteCreator);
}
deserializePart(part) { deserializePart(part) {
if (part.type === "command") { if (part.type === "command") {
return new CommandPart(part.text, this._autoCompleteCreator); return this.command(part.text);
} else { } else {
return super.deserializePart(part); return super.deserializePart(part);
} }