Add user status to DM rooms in the room list (#34191)

* Add user status to DM rooms in the room list

* Screenshot

* Tests for fetchUserStatus
This commit is contained in:
David Baker
2026-07-09 09:56:23 +00:00
committed by GitHub
parent 746ba6acab
commit 707d5a4353
11 changed files with 203 additions and 22 deletions
@@ -10,6 +10,12 @@ Please see LICENSE files in the repository root for full details.
* The emoji should be a single grapheme cluster.
*/
export interface UserStatus {
/**
* The emoji representing the user's status. This must be a single grapheme cluster.
*/
emoji: string;
/**
* The text representing the user's status.
*/
text: string;
}
@@ -6,7 +6,7 @@
*/
import React, { type JSX, memo, type ReactNode } from "react";
import { Text } from "@vector-im/compound-web";
import { Text, Tooltip } from "@vector-im/compound-web";
import classNames from "classnames";
import { Flex } from "../../../../core/utils/Flex";
@@ -54,7 +54,15 @@ export const RoomListItemContent = memo(function RoomListItemContent({
<div className={styles.ellipsis}>
<div className={styles.roomName} title={item.name} data-testid="room-name">
{item.name}
{item.userStatus && (
<Tooltip description={item.userStatus.text}>
<Text as="span" className={styles.userStatusEmoji}>
{item.userStatus.emoji}
</Text>
</Tooltip>
)}
</div>
{item.messagePreview && (
<Text as="div" size="sm" className={styles.ellipsis} title={item.messagePreview}>
{item.messagePreview}
@@ -99,6 +99,15 @@
text-overflow: ellipsis;
}
.roomName {
/* Allow the room name to shrink and truncate when displayed next to the user status emoji */
min-width: 0;
}
.userStatusEmoji {
padding-left: var(--cpd-space-1-5x);
}
.selected {
.container {
background-color: var(--cpd-color-bg-action-tertiary-selected);
@@ -314,3 +314,12 @@ export const SectionDisabled: Story = {
areSectionsEnabled: false,
},
};
export const WithUserStatus: Story = {
args: {
userStatus: {
emoji: "🌭",
text: "Hot",
},
},
};
@@ -16,6 +16,7 @@ import { RoomListItemContent } from "./RoomListItemContent";
import { type RoomNotifState } from "./RoomNotifs";
import styles from "./RoomListItemView.module.css";
import { useViewModel, type ViewModel } from "../../../../core/viewmodel";
import { type UserStatus } from "../../../../core/userStatus";
import { _t } from "../../../../core/i18n/i18n";
/**
@@ -72,6 +73,8 @@ export interface RoomListItemViewSnapshot {
isBold: boolean;
/** Optional message preview text */
messagePreview?: string;
/** The MSC4426 user status of the other user in a DM room, if any */
userStatus?: UserStatus;
/** Notification decoration data */
notification: NotificationDecorationData;
/** Whether the more options menu should be shown */
@@ -91,7 +91,7 @@ interface DisambiguatedProfileViewProps {
export function DisambiguatedProfileView({ vm, className }: Readonly<DisambiguatedProfileViewProps>): JSX.Element {
const { displayName, colorClass, displayIdentifier, title, emphasizeDisplayName, userStatus } = useViewModel(vm);
const userStatusEmoji = userStatus && [...new Intl.Segmenter().segment(userStatus.emoji)][0]?.segment;
const userStatusEmoji = userStatus && userStatus.emoji;
const displayNameClasses = classNames(colorClass, {
[styles.disambiguatedProfile_displayName]: emphasizeDisplayName,