Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -414,36 +414,58 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
const state = this.props.room.currentState;
const canChangeHistory = state?.mayClientSendStateEvent(EventType.RoomHistoryVisibility, client);

const options = [
{
value: HistoryVisibility.Shared,
label: _t("room_settings|security|history_visibility_shared"),
},
{
// Map 'joined' to 'invited' for display purposes
const displayHistory = history === HistoryVisibility.Joined ? HistoryVisibility.Invited : history;

const isPublicRoom = this.props.room.getJoinRule() === JoinRule.Public;
const isEncrypted = this.state.encrypted;

const options: Array<{ value: HistoryVisibility; label: string }> = [];

// 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) => <ExternalLink href="https://element.io/help#encryption20">{sub}</ExternalLink>,
},
)}
</>
);

return (
<SettingsFieldset legend={_t("room_settings|security|history_visibility_legend")} description={description}>
<StyledRadioGroup
name="historyVis"
value={history}
value={displayHistory}
onChange={this.onHistoryRadioToggle}
disabled={!canChangeHistory}
definitions={options}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@

getComponent(room);

expect(screen.getByText("Who can read history?").parentElement).toMatchSnapshot();

Check failure on line 316 in test/unit-tests/components/views/settings/tabs/room/SecurityRoomSettingsTab-test.tsx

View workflow job for this annotation

GitHub Actions / Jest (Element Web) (2)

<SecurityRoomSettingsTab /> › history visibility › uses shared as default history visibility when no state event found

expect(received).toMatchSnapshot() Snapshot name: `<SecurityRoomSettingsTab /> history visibility uses shared as default history visibility when no state event found 1` - Snapshot - 16 + Received + 3 @@ -10,24 +10,11 @@ class="mx_SettingsFieldset_description" > <div class="mx_SettingsSubsection_text" > - <span> - Changes won't affect past messages, only new ones. - <a - class="mx_ExternalLink" - href="https://element.io/help#encryption20" - rel="noreferrer noopener" - target="_blank" - > - Learn more - <i - class="mx_ExternalLink_icon" - /> - </a> - </span> + The visibility of existing history will not be changed. </div> </div> <div class="mx_SettingsFieldset_content" > @@ -44,11 +31,11 @@ <div /> </div> <div class="mx_StyledRadioButton_content" > - Members since invited + Members only (since they were invited) </div> <div class="mx_StyledRadioButton_spacer" /> </label> @@ -66,11 +53,11 @@ <div /> </div> <div class="mx_StyledRadioButton_content" > - Members (full history) + Members only (since the point in time of selecting this option) </div> <div class="mx_StyledRadioButton_spacer" /> </label> at Object.toMatchSnapshot (test/unit-tests/components/views/settings/tabs/room/SecurityRoomSettingsTab-test.tsx:316:77)
expect(screen.getByDisplayValue(HistoryVisibility.Shared)).toBeChecked();
});

Expand Down Expand Up @@ -377,6 +377,76 @@
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", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,20 @@ exports[`<SecurityRoomSettingsTab /> history visibility uses shared as default h
<div
class="mx_SettingsSubsection_text"
>
The visibility of existing history will not be changed.
<span>
Changes won't affect past messages, only new ones.
<a
class="mx_ExternalLink"
href="https://element.io/help#encryption20"
rel="noreferrer noopener"
target="_blank"
>
Learn more
<i
class="mx_ExternalLink_icon"
/>
</a>
</span>
</div>
</div>
<div
Expand All @@ -25,18 +38,18 @@ exports[`<SecurityRoomSettingsTab /> history visibility uses shared as default h
class="mx_StyledRadioButton mx_StyledRadioButton_enabled"
>
<input
id="historyVis-world_readable"
id="historyVis-invited"
name="historyVis"
type="radio"
value="world_readable"
value="invited"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
>
Anyone
Members since invited
</div>
<div
class="mx_StyledRadioButton_spacer"
Expand All @@ -58,49 +71,7 @@ exports[`<SecurityRoomSettingsTab /> history visibility uses shared as default h
<div
class="mx_StyledRadioButton_content"
>
Members only (since the point in time of selecting this option)
</div>
<div
class="mx_StyledRadioButton_spacer"
/>
</label>
<label
class="mx_StyledRadioButton mx_StyledRadioButton_enabled"
>
<input
id="historyVis-invited"
name="historyVis"
type="radio"
value="invited"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
>
Members only (since they were invited)
</div>
<div
class="mx_StyledRadioButton_spacer"
/>
</label>
<label
class="mx_StyledRadioButton mx_StyledRadioButton_enabled"
>
<input
id="historyVis-joined"
name="historyVis"
type="radio"
value="joined"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
>
Members only (since they joined)
Members (full history)
</div>
<div
class="mx_StyledRadioButton_spacer"
Expand Down
Loading