From fa6de481cef45afd1fb0208cce65718cc9405549 Mon Sep 17 00:00:00 2001 From: David Langley Date: Mon, 1 Dec 2025 19:27:13 +0000 Subject: [PATCH 1/2] Updates logic to match new spec --- .../tabs/room/SecurityRoomSettingsTab.tsx | 56 ++++++++++----- .../room/SecurityRoomSettingsTab-test.tsx | 71 +++++++++++++++++++ .../SecurityRoomSettingsTab-test.tsx.snap | 65 +++++------------ 3 files changed, 128 insertions(+), 64 deletions(-) diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx index 37faaea5d89..561270d4ac3 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx @@ -414,36 +414,58 @@ export default class SecurityRoomSettingsTab extends React.Component = []; + + // Show "invited" when room's join rule is NOT public OR E2EE is turned on, or if currently selected + if ( + !isPublicRoom || + isEncrypted || + history === HistoryVisibility.Invited || + history === HistoryVisibility.Joined + ) { + options.push({ value: HistoryVisibility.Invited, label: _t("room_settings|security|history_visibility_invited"), - }, - { - value: HistoryVisibility.Joined, - label: _t("room_settings|security|history_visibility_joined"), - }, - ]; + }); + } - // World readable doesn't make sense for encrypted rooms - if (!this.state.encrypted || history === HistoryVisibility.WorldReadable) { - options.unshift({ + // Always show "shared" option + options.push({ + value: HistoryVisibility.Shared, + label: _t("room_settings|security|history_visibility_shared"), + }); + + // Show "world_readable" when (is public AND not encrypted) OR currently selected + if ((isPublicRoom && !isEncrypted) || history === HistoryVisibility.WorldReadable) { + options.push({ value: HistoryVisibility.WorldReadable, label: _t("room_settings|security|history_visibility_world_readable"), }); } - const description = _t("room_settings|security|history_visibility_warning"); + const description = ( + <> + {_t( + "room_settings|security|history_visibility_warning", + {}, + { + a: (sub) => {sub}, + }, + )} + + ); return ( ", () => { expect(screen.getByDisplayValue(HistoryVisibility.Shared)).toBeChecked(); expect(logger.error).toHaveBeenCalledWith("oups"); }); + it("maps 'joined' history visibility to 'invited' for display", () => { + const room = new Room(roomId, client, userId); + setRoomStateEvents(room, undefined, undefined, HistoryVisibility.Joined); + + getComponent(room); + + // Should display as 'invited' even though underlying value is 'joined' + expect(screen.getByDisplayValue(HistoryVisibility.Invited)).toBeChecked(); + // Should not have a 'joined' option visible + expect(screen.queryByDisplayValue(HistoryVisibility.Joined)).not.toBeInTheDocument(); + }); + + it("shows 'invited' option for non-public rooms", () => { + const room = new Room(roomId, client, userId); + setRoomStateEvents(room, JoinRule.Invite); + + getComponent(room); + + expect(screen.getByDisplayValue(HistoryVisibility.Invited)).toBeInTheDocument(); + }); + + it("shows 'invited' option for encrypted rooms even if public", async () => { + const room = new Room(roomId, client, userId); + jest.spyOn(client.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true); + setRoomStateEvents(room, JoinRule.Public); + + getComponent(room); + + await waitFor(() => expect(screen.getByDisplayValue(HistoryVisibility.Invited)).toBeInTheDocument()); + }); + + it("does not show 'invited' option for public unencrypted rooms unless selected", async () => { + const room = new Room(roomId, client, userId); + setRoomStateEvents(room, JoinRule.Public, undefined, HistoryVisibility.Shared); + + getComponent(room); + + await waitFor(() => + expect(screen.queryByDisplayValue(HistoryVisibility.Invited)).not.toBeInTheDocument(), + ); + }); + + it("shows 'world_readable' option for public unencrypted rooms", async () => { + const room = new Room(roomId, client, userId); + setRoomStateEvents(room, JoinRule.Public); + + getComponent(room); + + await waitFor(() => expect(screen.getByDisplayValue(HistoryVisibility.WorldReadable)).toBeInTheDocument()); + }); + + it("does not show 'world_readable' option for private encrypted rooms unless selected", async () => { + const room = new Room(roomId, client, userId); + jest.spyOn(client.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true); + setRoomStateEvents(room, JoinRule.Invite); + + getComponent(room); + + await waitFor(() => + expect(screen.queryByDisplayValue(HistoryVisibility.WorldReadable)).not.toBeInTheDocument(), + ); + }); + + it("always shows 'shared' option", () => { + const room = new Room(roomId, client, userId); + setRoomStateEvents(room); + + getComponent(room); + + expect(screen.getByDisplayValue(HistoryVisibility.Shared)).toBeInTheDocument(); + }); }); describe("encryption", () => { diff --git a/test/unit-tests/components/views/settings/tabs/room/__snapshots__/SecurityRoomSettingsTab-test.tsx.snap b/test/unit-tests/components/views/settings/tabs/room/__snapshots__/SecurityRoomSettingsTab-test.tsx.snap index 920ef3c0bf6..0884f1b4de8 100644 --- a/test/unit-tests/components/views/settings/tabs/room/__snapshots__/SecurityRoomSettingsTab-test.tsx.snap +++ b/test/unit-tests/components/views/settings/tabs/room/__snapshots__/SecurityRoomSettingsTab-test.tsx.snap @@ -15,7 +15,20 @@ exports[` history visibility uses shared as default h
- The visibility of existing history will not be changed. + + Changes won't affect past messages, only new ones. + + Learn more + + +
history visibility uses shared as default h class="mx_StyledRadioButton mx_StyledRadioButton_enabled" >
@@ -36,7 +49,7 @@ exports[` history visibility uses shared as default h
- Anyone + Members since invited
history visibility uses shared as default h
- Members only (since the point in time of selecting this option) -
-
- -