Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import SettingsStore from "../../../../../settings/SettingsStore";
import { RoomPermalinkCreator } from "../../../../../utils/permalinks/Permalinks";
import { addReplyToMessageContent } from "../../../../../utils/Reply";

export const EMOTE_PREFIX = "/me ";

// Merges favouring the given relation
function attachRelation(content: IContent, relation?: IEventRelation): void {
if (relation) {
Expand Down Expand Up @@ -61,6 +63,8 @@ interface CreateMessageContentParams {
editedEvent?: MatrixEvent;
}

const isMatrixEvent = (e: MatrixEvent | undefined): e is MatrixEvent => e instanceof MatrixEvent;

export async function createMessageContent(
message: string,
isHTML: boolean,
Expand All @@ -72,22 +76,22 @@ export async function createMessageContent(
editedEvent,
}: CreateMessageContentParams,
): Promise<IContent> {
// TODO emote ?

const isEditing = Boolean(editedEvent);
const isReply = isEditing ? Boolean(editedEvent?.replyEventId) : Boolean(replyToEvent);
const isEditing = isMatrixEvent(editedEvent);
const isReply = isEditing ? Boolean(editedEvent.replyEventId) : isMatrixEvent(replyToEvent);
Comment on lines +79 to +80
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change allows TS to help us a bit more in the body of this big function, and saves us having to keep checking whether the event is undefined or not.

const isReplyAndEditing = isEditing && isReply;

/*const isEmote = containsEmote(model);
const isEmote = message.startsWith(EMOTE_PREFIX);
if (isEmote) {
model = stripEmoteCommand(model);
// if we are dealing with an emote we want to remove the prefix so that `/me` does not
// appear after the `* <userName>` text in the timeline
message = message.slice(EMOTE_PREFIX.length);
}
if (startsWith(model, "//")) {
model = stripPrefix(model, "/");
if (message.startsWith("//")) {
// if user wants to enter a single slash at the start of a message, this
// is how they have to do it (due to it clashing with commands), so here we
// remove the first character to make sure //word displays as /word
message = message.slice(1);
}
model = unescapeMessage(model);*/

// const body = textSerialize(model);

// if we're editing rich text, the message content is pure html
// BUT if we're not, the message content will be plain text
Expand All @@ -96,8 +100,7 @@ export async function createMessageContent(
const formattedBodyPrefix = (isReplyAndEditing && getHtmlReplyFallback(editedEvent)) || "";

const content: IContent = {
// TODO emote
msgtype: MsgType.Text,
msgtype: isEmote ? MsgType.Emote : MsgType.Text,
body: isEditing ? `${bodyPrefix} * ${body}` : body,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import dis from "../../../../../dispatcher/dispatcher";
import { createRedactEventDialog } from "../../../dialogs/ConfirmRedactDialog";
import { endEditing, cancelPreviousPendingEdit } from "./editing";
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
import { createMessageContent } from "./createMessageContent";
import { createMessageContent, EMOTE_PREFIX } from "./createMessageContent";
import { isContentModified } from "./isContentModified";
import { CommandCategories, getCommand } from "../../../../../SlashCommands";
import { runSlashCommand, shouldSendAnyway } from "../../../../../editor/commands";
Expand Down Expand Up @@ -78,11 +78,11 @@ export async function sendMessage(

let content: IContent | null = null;

// Functionality here approximates what can be found in SendMessageComposer.sendMessage()
if (message.startsWith("/") && !message.startsWith("//")) {
// Slash command handling here approximates what can be found in SendMessageComposer.sendMessage()
// but note that the /me and // special cases are handled by the call to createMessageContent
if (message.startsWith("/") && !message.startsWith("//") && !message.startsWith(EMOTE_PREFIX)) {
const { cmd, args } = getCommand(message);
if (cmd) {
// TODO handle /me special case separately, see end of SlashCommands.Commands
const threadId = relation?.rel_type === THREAD_RELATION_TYPE.name ? relation?.event_id : null;
let commandSuccessful: boolean;
[content, commandSuccessful] = await runSlashCommand(cmd, args, roomId, threadId ?? null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { MsgType } from "matrix-js-sdk/src/matrix";

import { mkEvent } from "../../../../../test-utils";
import { RoomPermalinkCreator } from "../../../../../../src/utils/permalinks/Permalinks";
import { createMessageContent } from "../../../../../../src/components/views/rooms/wysiwyg_composer/utils/createMessageContent";
import {
createMessageContent,
EMOTE_PREFIX,
} from "../../../../../../src/components/views/rooms/wysiwyg_composer/utils/createMessageContent";

describe("createMessageContent", () => {
const permalinkCreator = {
Expand Down Expand Up @@ -130,4 +134,24 @@ describe("createMessageContent", () => {
},
});
});

it("Should strip the /me prefix from a message", async () => {
const textBody = "some body text";
const content = await createMessageContent(EMOTE_PREFIX + textBody, true, { permalinkCreator });

expect(content).toMatchObject({ body: textBody, formatted_body: textBody });
});

it("Should strip single / from message prefixed with //", async () => {
const content = await createMessageContent("//twoSlashes", true, { permalinkCreator });

expect(content).toMatchObject({ body: "/twoSlashes", formatted_body: "/twoSlashes" });
});

it("Should set the content type to MsgType.Emote when /me prefix is used", async () => {
const textBody = "some body text";
const content = await createMessageContent(EMOTE_PREFIX + textBody, true, { permalinkCreator });

expect(content).toMatchObject({ msgtype: MsgType.Emote });
});
});