Add user status to dm room header (#34225)

* Add user status to dm room header

Also bumps the gap on the room header items to 8px because that's
what the designs have and I'm assuming it applies to everything, not
just the user status: pending design confirmation.

* Turns out the icons did have 8px gap

but via 4px of padding for reasons I can't discern

* Adjust spacing to 1.5x

as requested by design

* add tests

* Update screenshots

* add test for user status updating
This commit is contained in:
David Baker
2026-07-14 08:55:04 +00:00
committed by GitHub
parent b6859885a3
commit 2f612c3a9d
5 changed files with 56 additions and 3 deletions
@@ -18,6 +18,7 @@ import {
RoomStateEvent,
RoomMember,
type MatrixClient,
ClientEvent,
} from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { CryptoEvent, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
@@ -729,6 +730,17 @@ describe("RoomHeader", () => {
});
});
it("does not show a user status for non-DM rooms", async () => {
SettingsStore.setValue("feature_user_status", null, SettingLevel.DEVICE, true);
client.doesServerSupportExtendedProfiles = jest.fn().mockResolvedValue(true);
mocked(client.getExtendedProfileProperty).mockResolvedValue({ emoji: "🐎", text: "on a horse" });
render(<RoomHeader room={room} />, getWrapper());
expect(screen.queryByText("on a horse")).not.toBeInTheDocument();
expect(client.doesServerSupportExtendedProfiles).not.toHaveBeenCalled();
});
it("shows a history icon if the room is encrypted and has shared history", async () => {
mocked(client.getCrypto()!).isEncryptionEnabledInRoom.mockResolvedValue(true);
await room.addLiveEvents(
@@ -811,6 +823,42 @@ describe("RoomHeader", () => {
await waitFor(() => expect(getByLabelText(document.body, expectedLabel)).toBeInTheDocument());
});
it("shows the user status", async () => {
SettingsStore.setValue("feature_user_status", null, SettingLevel.DEVICE, true);
client.doesServerSupportExtendedProfiles = jest.fn().mockResolvedValue(true);
mocked(client.getExtendedProfileProperty).mockResolvedValue({ emoji: "🐎", text: "on a horse" });
render(<RoomHeader room={room} />, getWrapper());
await waitFor(() => expect(screen.getByText("on a horse")).toBeInTheDocument());
expect(screen.getByText("🐎")).toBeInTheDocument();
});
it("updates user status when it changes", async () => {
SettingsStore.setValue("feature_user_status", null, SettingLevel.DEVICE, true);
client.doesServerSupportExtendedProfiles = jest.fn().mockResolvedValue(true);
mocked(client.getExtendedProfileProperty).mockResolvedValue({ emoji: "🐎", text: "on a horse" });
render(<RoomHeader room={room} />, getWrapper());
mocked(client.getExtendedProfileProperty).mockResolvedValue({ emoji: "🐴", text: "is a horse" });
client.emit(ClientEvent.UserProfileUpdate, "@bob:example.org", { emoji: "🐴", text: "is a horse" });
await waitFor(() => expect(screen.getByText("is a horse")).toBeInTheDocument());
expect(screen.getByText("🐴")).toBeInTheDocument();
});
it("does not show the user status when the feature is disabled", async () => {
SettingsStore.setValue("feature_user_status", null, SettingLevel.DEVICE, false);
client.doesServerSupportExtendedProfiles = jest.fn().mockResolvedValue(true);
mocked(client.getExtendedProfileProperty).mockResolvedValue({ emoji: "🐎", text: "on a horse" });
render(<RoomHeader room={room} />, getWrapper());
expect(screen.queryByText("on a horse")).not.toBeInTheDocument();
expect(client.doesServerSupportExtendedProfiles).not.toHaveBeenCalled();
});
it("does not show the face pile for DMs", () => {
SdkConfig.put({
features: {