Show an icon in the room header for shared history (#31879)

* Show an icon in the room header for shared history

Add a decoration to the header for encrypted rooms with `history_visibility:
{shared|public}`.

Fixes: #31858

* Gate "shared history icon" behind labs flag

... since history isn't actually shared unless the flag is on

* Update snapshots

* update screenshot

* update screenshots, again

* exclude RRs from screenshot test
This commit is contained in:
Richard van der Hoff
2026-01-27 15:06:22 +00:00
committed by GitHub
parent a972340216
commit 617722018c
6 changed files with 67 additions and 8 deletions
@@ -60,6 +60,7 @@ import WidgetStore, { type IApp } from "../../../../../../src/stores/WidgetStore
import { UIFeature } from "../../../../../../src/settings/UIFeature";
import { SettingLevel } from "../../../../../../src/settings/SettingLevel";
import { ElementCallMemberEventType } from "../../../../../../src/call-types";
import { defaultWatchManager } from "../../../../../../src/settings/Settings.tsx";
jest.mock("../../../../../../src/utils/ShieldUtils");
jest.mock("../../../../../../src/hooks/right-panel/useCurrentPhase", () => ({
@@ -100,7 +101,7 @@ describe("RoomHeader", () => {
};
}
beforeEach(async () => {
beforeEach(() => {
client = stubClient();
room = new Room(ROOM_ID, client, "@alice:example.org", {
pendingEventOrdering: PendingEventOrdering.Detached,
@@ -708,6 +709,41 @@ describe("RoomHeader", () => {
});
});
it("shows a history icon if the room is encrypted and has shared history", async () => {
mocked(client.getCrypto()!).isEncryptionEnabledInRoom.mockResolvedValue(true);
await room.addLiveEvents(
[
new MatrixEvent({
type: "m.room.history_visibility",
content: { history_visibility: "shared" },
sender: MatrixClientPeg.get()!.getSafeUserId(),
state_key: "",
room_id: room.roomId,
}),
],
{ addToState: true },
);
let featureEnabled = true;
jest.spyOn(SettingsStore, "getValue").mockImplementation(
(flag) => flag === "feature_share_history_on_invite" && featureEnabled,
);
render(<RoomHeader room={room} />, getWrapper());
await waitFor(() => getByLabelText(document.body, "New members see history"));
// Disable the labs flag and check the icon disappears
featureEnabled = false;
act(() =>
defaultWatchManager.notifyUpdate(
"feature_share_history_on_invite",
null,
SettingLevel.DEVICE,
featureEnabled,
),
);
expect(queryByLabelText(document.body, "New members see history")).not.toBeInTheDocument();
});
describe("dm", () => {
beforeEach(() => {
// Make the mocked room a DM
@@ -56,7 +56,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
style="--cpd-icon-button-size: 100%;"
>
<svg
aria-labelledby="_r_12c_"
aria-labelledby="_r_134_"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
@@ -83,7 +83,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
style="--cpd-icon-button-size: 100%;"
>
<svg
aria-labelledby="_r_12h_"
aria-labelledby="_r_139_"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
@@ -98,7 +98,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
</button>
<button
aria-label="Threads"
aria-labelledby="_r_12m_"
aria-labelledby="_r_13e_"
class="_icon-button_1215g_8"
data-kind="primary"
role="button"
@@ -125,7 +125,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
</button>
<button
aria-label="Room info"
aria-labelledby="_r_12r_"
aria-labelledby="_r_13j_"
class="_icon-button_1215g_8"
data-kind="primary"
role="button"