diff --git a/src/autocomplete/CommandProvider.js b/src/autocomplete/CommandProvider.js index 609a8fa9a1..b13680ece2 100644 --- a/src/autocomplete/CommandProvider.js +++ b/src/autocomplete/CommandProvider.js @@ -64,6 +64,7 @@ export default class CommandProvider extends AutocompleteProvider { return matches.map((result) => ({ // 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 + ' '), + type: "command", component: ({ completion: groupId, suffix: ' ', + type: "community", href: makeGroupPermalink(groupId), component: ( } title="@room" description={_t("Notify the whole room")} /> diff --git a/src/autocomplete/RoomProvider.js b/src/autocomplete/RoomProvider.js index f118a06b9e..b94edf590c 100644 --- a/src/autocomplete/RoomProvider.js +++ b/src/autocomplete/RoomProvider.js @@ -89,6 +89,7 @@ export default class RoomProvider extends AutocompleteProvider { return { completion: displayAlias, completionId: displayAlias, + type: "room", suffix: ' ', href: makeRoomPermalink(displayAlias), component: ( diff --git a/src/autocomplete/UserProvider.js b/src/autocomplete/UserProvider.js index d4a5ec5e74..62ae5d4970 100644 --- a/src/autocomplete/UserProvider.js +++ b/src/autocomplete/UserProvider.js @@ -114,6 +114,7 @@ export default class UserProvider extends AutocompleteProvider { // relies on the length of the entity === length of the text in the decoration. completion: user.rawDisplayName, completionId: user.userId, + type: "user", suffix: (selection.beginning && range.start === 0) ? ': ' : ' ', href: makeUserPermalink(user.userId), component: ( diff --git a/src/editor/autocomplete.js b/src/editor/autocomplete.js index beb155f297..3ee69dc477 100644 --- a/src/editor/autocomplete.js +++ b/src/editor/autocomplete.js @@ -100,19 +100,21 @@ export default class AutocompleteWrapperModel { _partForCompletion(completion) { const {completionId} = completion; const text = completion.completion; - const firstChr = completionId && completionId[0]; - switch (firstChr) { - case "@": { - if (completionId === "@room") { - return [this._partCreator.atRoomPill(completionId)]; - } else { - return this._partCreator.createMentionParts(this._partIndex, text, completionId); - } - } - case "#": + switch (completion.type) { + case "room": 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: + // used for emoji and other plain text completion replacement return [this._partCreator.plain(text)]; } } diff --git a/src/editor/parts.js b/src/editor/parts.js index 883eff8679..f0b713beb6 100644 --- a/src/editor/parts.js +++ b/src/editor/parts.js @@ -456,15 +456,20 @@ export class CommandPartCreator extends PartCreator { createPartForInput(text, partIndex) { // at beginning and starts with /? create if (partIndex === 0 && text[0] === "/") { - return new CommandPart("", this._autoCompleteCreator); + // text will be inserted by model, so pass empty string + return this.command(""); } else { return super.createPartForInput(text, partIndex); } } + command(text) { + return new CommandPart(text, this._autoCompleteCreator); + } + deserializePart(part) { if (part.type === "command") { - return new CommandPart(part.text, this._autoCompleteCreator); + return this.command(part.text); } else { return super.deserializePart(part); }