Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit ac3c95f

Browse files
authored
Directly convert Matrix and room Ids to pills (#10267)
1 parent de6a1a6 commit ac3c95f

File tree

2 files changed

+51
-54
lines changed

2 files changed

+51
-54
lines changed

src/components/views/messages/TextualBody.tsx

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import React, { createRef, SyntheticEvent, MouseEvent, ReactNode } from "react";
17+
import React, { createRef, SyntheticEvent, MouseEvent } from "react";
1818
import ReactDOM from "react-dom";
1919
import highlight from "highlight.js";
2020
import { MsgType } from "matrix-js-sdk/src/@types/event";
@@ -86,21 +86,21 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
8686
}
8787

8888
private applyFormatting(): void {
89+
// Function is only called from render / componentDidMount → contentRef is set
90+
const content = this.contentRef.current!;
91+
8992
const showLineNumbers = SettingsStore.getValue("showCodeLineNumbers");
90-
this.activateSpoilers([this.contentRef.current]);
93+
this.activateSpoilers([content]);
9194

92-
// pillifyLinks BEFORE linkifyElement because plain room/user URLs in the composer
93-
// are still sent as plaintext URLs. If these are ever pillified in the composer,
94-
// we should be pillify them here by doing the linkifying BEFORE the pillifying.
95-
pillifyLinks([this.contentRef.current], this.props.mxEvent, this.pills);
96-
HtmlUtils.linkifyElement(this.contentRef.current);
95+
HtmlUtils.linkifyElement(content);
96+
pillifyLinks([content], this.props.mxEvent, this.pills);
9797

9898
this.calculateUrlPreview();
9999

100100
// tooltipifyLinks AFTER calculateUrlPreview because the DOM inside the tooltip
101101
// container is empty before the internal component has mounted so calculateUrlPreview
102102
// won't find any anchors
103-
tooltipifyLinks([this.contentRef.current], this.pills, this.tooltips);
103+
tooltipifyLinks([content], this.pills, this.tooltips);
104104

105105
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") {
106106
// Handle expansion and add buttons
@@ -578,18 +578,16 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
578578

579579
// only strip reply if this is the original replying event, edits thereafter do not have the fallback
580580
const stripReply = !mxEvent.replacingEvent() && !!getParentEventId(mxEvent);
581-
let body: ReactNode;
582-
if (!body) {
583-
isEmote = content.msgtype === MsgType.Emote;
584-
isNotice = content.msgtype === MsgType.Notice;
585-
body = HtmlUtils.bodyToHtml(content, this.props.highlights, {
586-
disableBigEmoji: isEmote || !SettingsStore.getValue<boolean>("TextualBody.enableBigEmoji"),
587-
// Part of Replies fallback support
588-
stripReplyFallback: stripReply,
589-
ref: this.contentRef,
590-
returnString: false,
591-
});
592-
}
581+
isEmote = content.msgtype === MsgType.Emote;
582+
isNotice = content.msgtype === MsgType.Notice;
583+
let body = HtmlUtils.bodyToHtml(content, this.props.highlights, {
584+
disableBigEmoji: isEmote || !SettingsStore.getValue<boolean>("TextualBody.enableBigEmoji"),
585+
// Part of Replies fallback support
586+
stripReplyFallback: stripReply,
587+
ref: this.contentRef,
588+
returnString: false,
589+
});
590+
593591
if (this.props.replacingEventId) {
594592
body = (
595593
<>

test/components/views/messages/TextualBody-test.tsx

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
1919
import { MockedObject } from "jest-mock";
2020
import { render } from "@testing-library/react";
2121

22-
import { getMockClientWithEventEmitter, mkEvent, mkStubRoom } from "../../../test-utils";
22+
import { getMockClientWithEventEmitter, mkEvent, mkMessage, mkStubRoom } from "../../../test-utils";
2323
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
2424
import * as languageHandler from "../../../../src/languageHandler";
2525
import DMRoomMap from "../../../../src/utils/DMRoomMap";
@@ -28,6 +28,15 @@ import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
2828
import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks";
2929
import { MediaEventHelper } from "../../../../src/utils/MediaEventHelper";
3030

31+
const mkRoomTextMessage = (body: string): MatrixEvent => {
32+
return mkMessage({
33+
msg: body,
34+
room: "room_id",
35+
user: "sender",
36+
event: true,
37+
});
38+
};
39+
3140
describe("<TextualBody />", () => {
3241
afterEach(() => {
3342
jest.spyOn(MatrixClientPeg, "get").mockRestore();
@@ -38,9 +47,11 @@ describe("<TextualBody />", () => {
3847
beforeEach(() => {
3948
defaultMatrixClient = getMockClientWithEventEmitter({
4049
getRoom: () => defaultRoom,
50+
getRooms: () => [defaultRoom],
4151
getAccountData: (): MatrixEvent | undefined => undefined,
4252
isGuest: () => false,
4353
mxcUrlToHttp: (s: string) => s,
54+
getUserId: () => "@user:example.com",
4455
});
4556
});
4657

@@ -116,17 +127,7 @@ describe("<TextualBody />", () => {
116127
});
117128

118129
it("simple message renders as expected", () => {
119-
const ev = mkEvent({
120-
type: "m.room.message",
121-
room: "room_id",
122-
user: "sender",
123-
content: {
124-
body: "this is a plaintext message",
125-
msgtype: "m.text",
126-
},
127-
event: true,
128-
});
129-
130+
const ev = mkRoomTextMessage("this is a plaintext message");
130131
const { container } = getComponent({ mxEvent: ev });
131132
expect(container).toHaveTextContent(ev.getContent().body);
132133
const content = container.querySelector(".mx_EventTile_body");
@@ -135,17 +136,7 @@ describe("<TextualBody />", () => {
135136

136137
// If pills were rendered within a Portal/same shadow DOM then it'd be easier to test
137138
it("linkification get applied correctly into the DOM", () => {
138-
const ev = mkEvent({
139-
type: "m.room.message",
140-
room: "room_id",
141-
user: "sender",
142-
content: {
143-
body: "Visit https://matrix.org/",
144-
msgtype: "m.text",
145-
},
146-
event: true,
147-
});
148-
139+
const ev = mkRoomTextMessage("Visit https://matrix.org/");
149140
const { container } = getComponent({ mxEvent: ev });
150141
expect(container).toHaveTextContent(ev.getContent().body);
151142
const content = container.querySelector(".mx_EventTile_body");
@@ -155,6 +146,24 @@ describe("<TextualBody />", () => {
155146
"https://matrix.org/</a></span>",
156147
);
157148
});
149+
150+
it("pillification of MXIDs get applied correctly into the DOM", () => {
151+
const ev = mkRoomTextMessage("Chat with @user:example.com");
152+
const { container } = getComponent({ mxEvent: ev });
153+
const content = container.querySelector(".mx_EventTile_body");
154+
expect(content.innerHTML).toMatchInlineSnapshot(
155+
`"Chat with <span><bdi><a class="mx_Pill mx_UserPill"><img class="mx_BaseAvatar mx_BaseAvatar_image" src="mxc://avatar.url/image.png" style="width: 16px; height: 16px;" alt="" data-testid="avatar-img" aria-hidden="true"><span class="mx_Pill_linkText">Member</span></a></bdi></span>"`,
156+
);
157+
});
158+
159+
it("pillification of room aliases get applied correctly into the DOM", () => {
160+
const ev = mkRoomTextMessage("Visit #room:example.com");
161+
const { container } = getComponent({ mxEvent: ev });
162+
const content = container.querySelector(".mx_EventTile_body");
163+
expect(content.innerHTML).toMatchInlineSnapshot(
164+
`"Visit <span><bdi><a class="mx_Pill mx_RoomPill" href="https://matrix.to/#/#room:example.com"><span class="mx_Pill_linkText">#room:example.com</span></a></bdi></span>"`,
165+
);
166+
});
158167
});
159168

160169
describe("renders formatted m.text correctly", () => {
@@ -382,17 +391,7 @@ describe("<TextualBody />", () => {
382391
});
383392
DMRoomMap.makeShared();
384393

385-
const ev = mkEvent({
386-
type: "m.room.message",
387-
room: "room_id",
388-
user: "sender",
389-
content: {
390-
body: "Visit https://matrix.org/",
391-
msgtype: "m.text",
392-
},
393-
event: true,
394-
});
395-
394+
const ev = mkRoomTextMessage("Visit https://matrix.org/");
396395
const { container, rerender } = getComponent(
397396
{ mxEvent: ev, showUrlPreview: true, onHeightChanged: jest.fn() },
398397
matrixClient,

0 commit comments

Comments
 (0)