Improve rendering of empty topics in the timeline (#29152)

* Improve display of empty topic events in the timeline.

* Use topic parser for topic events.

* Revert changes i18n for the moment

* Use the correct import pattern

* Add tests for topic rendering
This commit is contained in:
Will Hunt
2025-02-04 12:18:54 +00:00
committed by GitHub
parent 1ea1d386ab
commit 8cae1e9f5e
4 changed files with 62 additions and 7 deletions
+10 -4
View File
@@ -17,6 +17,7 @@ import {
MsgType,
M_POLL_START,
M_POLL_END,
ContentHelpers,
} from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger";
@@ -227,11 +228,16 @@ function textForMemberEvent(
function textForTopicEvent(ev: MatrixEvent): (() => string) | null {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
const topic = ContentHelpers.parseTopicContent(ev.getContent()).text;
return () =>
_t("timeline|m.room.topic", {
senderDisplayName,
topic: ev.getContent().topic,
});
topic
? _t("timeline|m.room.topic|changed", {
senderDisplayName,
topic,
})
: _t("timeline|m.room.topic|removed", {
senderDisplayName,
});
}
function textForRoomAvatarEvent(ev: MatrixEvent): (() => string) | null {
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
import React, { createRef } from "react";
import classNames from "classnames";
import { EventType } from "matrix-js-sdk/src/matrix";
import { ContentHelpers, EventType } from "matrix-js-sdk/src/matrix";
import { _t } from "../../../languageHandler";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
@@ -51,7 +51,7 @@ export default class RoomProfileSettings extends React.Component<IProps, IState>
const avatarUrl = avatarEvent?.getContent()["url"] ?? null;
const topicEvent = room.currentState.getStateEvents(EventType.RoomTopic, "");
const topic = topicEvent && topicEvent.getContent() ? topicEvent.getContent()["topic"] : "";
const topic = (topicEvent && ContentHelpers.parseTopicContent(topicEvent.getContent()).text) || "";
const nameEvent = room.currentState.getStateEvents(EventType.RoomName, "");
const name = nameEvent && nameEvent.getContent() ? nameEvent.getContent()["name"] : "";
@@ -145,6 +145,8 @@ export default class RoomProfileSettings extends React.Component<IProps, IState>
if (this.state.originalTopic !== this.state.topic) {
const html = htmlSerializeFromMdIfNeeded(this.state.topic, { forceHTML: false });
// XXX: Note that we deliberately send an empty string on an empty topic rather
// than a clearer `undefined` value. Synapse still requires a string in a topic.
await client.setRoomTopic(this.props.roomId, this.state.topic, html);
newState.originalTopic = this.state.topic;
}
+4 -1
View File
@@ -3493,7 +3493,10 @@
"sent": "%(senderName)s sent an invitation to %(targetDisplayName)s to join the room."
},
"m.room.tombstone": "%(senderDisplayName)s upgraded this room.",
"m.room.topic": "%(senderDisplayName)s changed the topic to \"%(topic)s\".",
"m.room.topic": {
"changed": "%(senderDisplayName)s changed the topic to \"%(topic)s\".",
"removed": "%(senderDisplayName)s removed the topic."
},
"m.sticker": "%(senderDisplayName)s sent a sticker.",
"m.video": {
"error_decrypting": "Error decrypting video"