diff --git a/src/components/views/rooms/wysiwyg_composer/message.ts b/src/components/views/rooms/wysiwyg_composer/message.ts
index c1569324ef1..5569af02a95 100644
--- a/src/components/views/rooms/wysiwyg_composer/message.ts
+++ b/src/components/views/rooms/wysiwyg_composer/message.ts
@@ -22,13 +22,23 @@ import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread";
import { PosthogAnalytics } from "../../../../PosthogAnalytics";
import SettingsStore from "../../../../settings/SettingsStore";
import { decorateStartSendingTime, sendRoundTripMetric } from "../../../../sendTimePerformanceMetrics";
-import { attachRelation } from "../SendMessageComposer";
import { RoomPermalinkCreator } from "../../../../utils/permalinks/Permalinks";
import { doMaybeLocalRoomAction } from "../../../../utils/local-room";
import { CHAT_EFFECTS } from "../../../../effects";
import { containsEmoji } from "../../../../effects/utils";
import { IRoomState } from "../../../structures/RoomView";
import dis from '../../../../dispatcher/dispatcher';
+import { addReplyToMessageContent } from "../../../../utils/Reply";
+
+// Merges favouring the given relation
+function attachRelation(content: IContent, relation?: IEventRelation): void {
+ if (relation) {
+ content['m.relates_to'] = {
+ ...(content['m.relates_to'] || {}),
+ ...relation,
+ };
+ }
+}
interface SendMessageParams {
mxClient: MatrixClient;
@@ -81,13 +91,12 @@ export function createMessageContent(
attachRelation(content, relation);
- // TODO reply
- /*if (replyToEvent) {
+ if (replyToEvent) {
addReplyToMessageContent(content, replyToEvent, {
permalinkCreator,
includeLegacyFallback: includeReplyLegacyFallback,
});
- }*/
+ }
return content;
}
@@ -148,8 +157,7 @@ export function sendMessage(
mxClient,
);
- // TODO reply
- /*if (replyToEvent) {
+ if (replyToEvent) {
// Clear reply_to_event as we put the message into the queue
// if the send fails, retry will handle resending.
dis.dispatch({
@@ -157,7 +165,8 @@ export function sendMessage(
event: null,
context: roomContext.timelineRenderingType,
});
- }*/
+ }
+
dis.dispatch({ action: "message_sent" });
CHAT_EFFECTS.forEach((effect) => {
if (containsEmoji(content, effect.emojis)) {
diff --git a/test/components/views/rooms/wysiwyg_composer/message-test.ts b/test/components/views/rooms/wysiwyg_composer/message-test.ts
index 605b3e35a7e..712b671c9f7 100644
--- a/test/components/views/rooms/wysiwyg_composer/message-test.ts
+++ b/test/components/views/rooms/wysiwyg_composer/message-test.ts
@@ -22,9 +22,14 @@ import { createTestClient, mkEvent, mkStubRoom } from "../../../../test-utils";
import defaultDispatcher from "../../../../../src/dispatcher/dispatcher";
import SettingsStore from "../../../../../src/settings/SettingsStore";
import { SettingLevel } from "../../../../../src/settings/SettingLevel";
+import { RoomPermalinkCreator } from "../../../../../src/utils/permalinks/Permalinks";
describe('message', () => {
- const permalinkCreator = jest.fn() as any;
+ const permalinkCreator = {
+ forEvent(eventId: string): string {
+ return "$$permalink$$";
+ },
+ } as RoomPermalinkCreator;
const message = 'hello world';
const mockEvent = mkEvent({
type: "m.room.message",
@@ -45,10 +50,51 @@ describe('message', () => {
// Then
expect(content).toEqual({
- body: message,
- format: "org.matrix.custom.html",
- formatted_body: message,
- msgtype: "m.text",
+ "body": message,
+ "format": "org.matrix.custom.html",
+ "formatted_body": message,
+ "msgtype": "m.text",
+ });
+ });
+
+ it('Should add reply to message content', () => {
+ // When
+ const content = createMessageContent(message, { permalinkCreator, replyToEvent: mockEvent });
+
+ // Then
+ expect(content).toEqual({
+ "body": "> Replying to this\n\nhello world",
+ "format": "org.matrix.custom.html",
+ "formatted_body": "In reply to" +
+ " myfakeuser"+
+ "
Replying to this
hello world",
+ "msgtype": "m.text",
+ "m.relates_to": {
+ "m.in_reply_to": {
+ "event_id": mockEvent.getId(),
+ },
+ },
+ });
+ });
+
+ it("Should add relation to message", () => {
+ // When
+ const relation = {
+ rel_type: "m.thread",
+ event_id: "myFakeThreadId",
+ };
+ const content = createMessageContent(message, { permalinkCreator, relation });
+
+ // Then
+ expect(content).toEqual({
+ "body": message,
+ "format": "org.matrix.custom.html",
+ "formatted_body": message,
+ "msgtype": "m.text",
+ "m.relates_to": {
+ "event_id": "myFakeThreadId",
+ "rel_type": "m.thread",
+ },
});
});
});
@@ -102,6 +148,15 @@ describe('message', () => {
const spyDispatcher = jest.spyOn(defaultDispatcher, "dispatch");
it('Should not send empty html message', async () => {
+ // When
+ await sendMessage('', { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator });
+
+ // Then
+ expect(mockClient.sendMessage).toBeCalledTimes(0);
+ expect(spyDispatcher).toBeCalledTimes(0);
+ });
+
+ it('Should send html message', async () => {
// When
await sendMessage(message, { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator });
@@ -116,13 +171,44 @@ describe('message', () => {
expect(spyDispatcher).toBeCalledWith({ action: 'message_sent' });
});
- it('Should send html message', async () => {
+ it('Should send reply to html message', async () => {
+ const mockReplyEvent = mkEvent({
+ type: "m.room.message",
+ room: 'myfakeroom',
+ user: 'myfakeuser2',
+ content: { "msgtype": "m.text", "body": "My reply" },
+ event: true,
+ });
+
// When
- await sendMessage('', { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator });
+ await sendMessage(message, {
+ roomContext: defaultRoomContext,
+ mxClient: mockClient,
+ permalinkCreator,
+ replyToEvent: mockReplyEvent,
+ });
// Then
- expect(mockClient.sendMessage).toBeCalledTimes(0);
- expect(spyDispatcher).toBeCalledTimes(0);
+ expect(spyDispatcher).toBeCalledWith({
+ action: 'reply_to_event',
+ event: null,
+ context: defaultRoomContext.timelineRenderingType,
+ });
+
+ const expectedContent = {
+ "body": "> My reply\n\nhello world",
+ "format": "org.matrix.custom.html",
+ "formatted_body": "In reply to" +
+ " myfakeuser2" +
+ "
My reply
hello world",
+ "msgtype": "m.text",
+ "m.relates_to": {
+ "m.in_reply_to": {
+ "event_id": mockReplyEvent.getId(),
+ },
+ },
+ };
+ expect(mockClient.sendMessage).toBeCalledWith('myfakeroom', null, expectedContent);
});
it('Should scroll to bottom after sending a html message', async () => {