Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reply support to WysiwygComposer #9422

Merged
merged 5 commits into from Oct 14, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 16 additions & 7 deletions src/components/views/rooms/wysiwyg_composer/message.ts
Expand Up @@ -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;
Expand Down Expand Up @@ -81,13 +91,12 @@ export function createMessageContent(

attachRelation(content, relation);

// TODO reply
/*if (replyToEvent) {
if (replyToEvent) {
addReplyToMessageContent(content, replyToEvent, {
permalinkCreator,
includeLegacyFallback: includeReplyLegacyFallback,
});
}*/
}

return content;
}
Expand Down Expand Up @@ -148,16 +157,16 @@ 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({
action: 'reply_to_event',
event: null,
context: roomContext.timelineRenderingType,
});
}*/
}

dis.dispatch({ action: "message_sent" });
CHAT_EFFECTS.forEach((effect) => {
if (containsEmoji(content, effect.emojis)) {
Expand Down
104 changes: 95 additions & 9 deletions test/components/views/rooms/wysiwyg_composer/message-test.ts
Expand Up @@ -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 = '<i><b>hello</b> world</i>';
const mockEvent = mkEvent({
type: "m.room.message",
Expand All @@ -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": "> <myfakeuser> Replying to this\n\n<i><b>hello</b> world</i>",
"format": "org.matrix.custom.html",
"formatted_body": "<mx-reply><blockquote><a href=\"$$permalink$$\">In reply to</a>" +
" <a href=\"https://matrix.to/#/myfakeuser\">myfakeuser</a>"+
"<br>Replying to this</blockquote></mx-reply><i><b>hello</b> world</i>",
"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",
},
});
});
});
Expand Down Expand Up @@ -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 });

Expand All @@ -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": "> <myfakeuser2> My reply\n\n<i><b>hello</b> world</i>",
"format": "org.matrix.custom.html",
"formatted_body": "<mx-reply><blockquote><a href=\"$$permalink$$\">In reply to</a>" +
" <a href=\"https://matrix.to/#/myfakeuser2\">myfakeuser2</a>" +
"<br>My reply</blockquote></mx-reply><i><b>hello</b> world</i>",
"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 () => {
Expand Down