diff --git a/src/app/features/common-settings/general/RoomProfile.tsx b/src/app/features/common-settings/general/RoomProfile.tsx
index 87aa3d4db..ee283fcd4 100644
--- a/src/app/features/common-settings/general/RoomProfile.tsx
+++ b/src/app/features/common-settings/general/RoomProfile.tsx
@@ -41,6 +41,32 @@ import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
import { useAlive } from '../../../hooks/useAlive';
import { RoomPermissionsAPI } from '../../../hooks/useRoomPermissions';
+const MARKDOWN_PATTERN = /(\*\*|__|\*|_|~~|`|\[.+?\]\(.+?\))/;
+
+function topicMarkdownToHtml(text: string): string {
+ return text
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/\*\*(.+?)\*\*/g, '$1')
+ .replace(/__(.+?)__/g, '$1')
+ .replace(/\*(.+?)\*/g, '$1')
+ .replace(/_(.+?)_/g, '$1')
+ .replace(/~~(.+?)~~/g, '$1')
+ .replace(/`(.+?)`/g, '$1')
+ .replace(/\[(.+?)\]\((.+?)\)/g, '$1')
+ .replace(/\n/g, '
');
+}
+
+function buildTopicContent(topic: string): Record {
+ if (!MARKDOWN_PATTERN.test(topic)) return { topic };
+ return {
+ topic,
+ format: 'org.matrix.custom.html',
+ formatted_body: topicMarkdownToHtml(topic),
+ };
+}
+
type RoomProfileEditProps = {
canEditAvatar: boolean;
canEditName: boolean;
@@ -101,7 +127,8 @@ export function RoomProfileEdit({
await mx.sendStateEvent(room.roomId, StateEvent.RoomName as any, { name: roomName });
}
if (roomTopic !== undefined) {
- await mx.sendStateEvent(room.roomId, StateEvent.RoomTopic as any, { topic: roomTopic });
+ const topicContent = buildTopicContent(roomTopic);
+ await mx.sendStateEvent(room.roomId, StateEvent.RoomTopic as any, topicContent);
}
},
[mx, room.roomId],
@@ -224,10 +251,16 @@ export function RoomProfileEdit({
+ {canEditTopic && (
+
+ Supports markdown: **bold**, *italic*, ~~strikethrough~~, `code`, [text](url)
+
+ )}
{submitState.status === AsyncStatus.Error && (
diff --git a/src/app/features/room-nav/RoomNavItem.tsx b/src/app/features/room-nav/RoomNavItem.tsx
index 07a68d5bf..9d0a61ca7 100644
--- a/src/app/features/room-nav/RoomNavItem.tsx
+++ b/src/app/features/room-nav/RoomNavItem.tsx
@@ -214,6 +214,7 @@ const RoomNavItemMenu = forwardRef(
const space = useSpaceOptionally();
const [invitePrompt, setInvitePrompt] = useState(false);
+ const isServerNotice = room.getType() === 'm.server_notice';
const handleMarkAsRead = () => {
markAsRead(mx, room.roomId, hideActivity);
@@ -320,16 +321,18 @@ const RoomNavItemMenu = forwardRef(
Rename for me…
- }
- radii="300"
- >
-
- Room Settings
-
-
+ {!isServerNotice && (
+ }
+ radii="300"
+ >
+
+ Room Settings
+
+
+ )}
diff --git a/src/app/features/room/ReportRoomModal.tsx b/src/app/features/room/ReportRoomModal.tsx
index 7a1c39acc..772f58dbc 100644
--- a/src/app/features/room/ReportRoomModal.tsx
+++ b/src/app/features/room/ReportRoomModal.tsx
@@ -67,16 +67,19 @@ export function ReportRoomModal({ roomId, onClose }: ReportRoomModalProps) {
submitReport(fullReason);
};
- const errcode =
+ const reportError =
reportState.status === AsyncStatus.Error
- ? (reportState.error as { errcode?: string })?.errcode
+ ? (reportState.error as { errcode?: string; httpStatus?: number })
: undefined;
+ const errcode = reportError?.errcode;
const errorMsg =
errcode === 'M_LIMIT_EXCEEDED'
? 'You are being rate limited. Please wait before reporting again.'
: errcode === 'M_FORBIDDEN'
? 'You cannot report this room.'
- : 'Failed to submit report. Please try again.';
+ : errcode === 'M_UNRECOGNIZED' || reportError?.httpStatus === 404
+ ? 'Room reporting is not supported by your homeserver.'
+ : 'Failed to submit report. Please try again.';
return (
}>
diff --git a/src/app/features/room/RoomViewHeader.tsx b/src/app/features/room/RoomViewHeader.tsx
index 2993a08b5..4d115aca9 100644
--- a/src/app/features/room/RoomViewHeader.tsx
+++ b/src/app/features/room/RoomViewHeader.tsx
@@ -49,7 +49,6 @@ import { roomToUnreadAtom } from '../../state/room/roomToUnread';
import { copyToClipboard } from '../../utils/dom';
import { LeaveRoomPrompt } from '../../components/leave-room-prompt';
import { useRoomAvatar, useLocalRoomName, useRoomTopic } from '../../hooks/useRoomMeta';
-import { useReportRoomSupported } from '../../hooks/useReportRoomSupported';
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
import { stopPropagation } from '../../utils/keyboard';
import { getMatrixToRoom } from '../../plugins/matrix-to';
@@ -90,7 +89,6 @@ const RoomMenu = forwardRef(({ room, requestClose
const permissions = useRoomPermissions(creators, powerLevels);
const canInvite = permissions.action('invite', mx.getSafeUserId());
- const reportRoomSupported = useReportRoomSupported();
const isServerNotice = room.getType() === 'm.server_notice';
const isCreator = creators.has(mx.getSafeUserId());
const notificationPreferences = useRoomsNotificationPreferencesContext();
@@ -247,7 +245,7 @@ const RoomMenu = forwardRef(({ room, requestClose
- {reportRoomSupported && !isServerNotice && !isCreator && (
+ {!isServerNotice && !isCreator && (