Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 0059c7c

Browse files
authored
Allow setting knock room directory visibility (#11529)
* Allow setting knock room directory visibility Signed-off-by: Charly Nguyen <[email protected]> * Apply PR feedback Signed-off-by: Charly Nguyen <[email protected]> --------- Signed-off-by: Charly Nguyen <[email protected]>
1 parent 77b681e commit 0059c7c

File tree

4 files changed

+122
-6
lines changed

4 files changed

+122
-6
lines changed

res/css/views/settings/_JoinRuleSettings.pcss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,8 @@ limitations under the License.
7474
}
7575
}
7676
}
77+
78+
.mx_JoinRuleSettings_labelledCheckbox {
79+
font: var(--cpd-font-body-md-regular);
80+
margin-top: var(--cpd-space-2x);
81+
}

src/components/views/settings/JoinRuleSettings.tsx

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,15 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import React, { ReactNode } from "react";
18-
import { IJoinRuleEventContent, JoinRule, RestrictedAllowType, Room, EventType } from "matrix-js-sdk/src/matrix";
17+
import React, { ReactNode, useEffect, useState } from "react";
18+
import {
19+
IJoinRuleEventContent,
20+
JoinRule,
21+
RestrictedAllowType,
22+
Room,
23+
EventType,
24+
Visibility,
25+
} from "matrix-js-sdk/src/matrix";
1926

2027
import StyledRadioGroup, { IDefinition } from "../elements/StyledRadioGroup";
2128
import { _t } from "../../../languageHandler";
@@ -34,6 +41,7 @@ import { Action } from "../../../dispatcher/actions";
3441
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
3542
import { doesRoomVersionSupport, PreferredRoomVersions } from "../../../utils/PreferredRoomVersions";
3643
import SettingsStore from "../../../settings/SettingsStore";
44+
import LabelledCheckbox from "../elements/LabelledCheckbox";
3745

3846
export interface JoinRuleSettingsProps {
3947
room: Room;
@@ -76,6 +84,22 @@ const JoinRuleSettings: React.FC<JoinRuleSettingsProps> = ({
7684
? content?.allow?.filter((o) => o.type === RestrictedAllowType.RoomMembership).map((o) => o.room_id)
7785
: undefined;
7886

87+
const [isPublicKnockRoom, setIsPublicKnockRoom] = useState(false);
88+
89+
useEffect(() => {
90+
if (joinRule === JoinRule.Knock) {
91+
cli.getRoomDirectoryVisibility(room.roomId)
92+
.then(({ visibility }) => setIsPublicKnockRoom(visibility === Visibility.Public))
93+
.catch(onError);
94+
}
95+
}, [cli, joinRule, onError, room.roomId]);
96+
97+
const onIsPublicKnockRoomChange = (checked: boolean): void => {
98+
cli.setRoomDirectoryVisibility(room.roomId, checked ? Visibility.Public : Visibility.Private)
99+
.then(() => setIsPublicKnockRoom(checked))
100+
.catch(onError);
101+
};
102+
79103
const editRestrictedRoomIds = async (): Promise<string[] | undefined> => {
80104
let selected = restrictedAllowRoomIds;
81105
if (!selected?.length && SpaceStore.instance.activeSpaceRoom) {
@@ -297,7 +321,22 @@ const JoinRuleSettings: React.FC<JoinRuleSettingsProps> = ({
297321
{preferredKnockVersion && upgradeRequiredPill}
298322
</>
299323
),
300-
description: _t("People cannot join unless access is granted."),
324+
description: (
325+
<>
326+
{_t("People cannot join unless access is granted.")}
327+
<LabelledCheckbox
328+
className="mx_JoinRuleSettings_labelledCheckbox"
329+
disabled={joinRule !== JoinRule.Knock}
330+
label={
331+
room.isSpaceRoom()
332+
? _t("Make this space visible in the public room directory.")
333+
: _t("Make this room visible in the public room directory.")
334+
}
335+
onChange={onIsPublicKnockRoomChange}
336+
value={isPublicKnockRoom}
337+
/>
338+
</>
339+
),
301340
});
302341
}
303342

src/i18n/strings/en_EN.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1492,6 +1492,8 @@
14921492
"Space members": "Space members",
14931493
"Ask to join": "Ask to join",
14941494
"People cannot join unless access is granted.": "People cannot join unless access is granted.",
1495+
"Make this space visible in the public room directory.": "Make this space visible in the public room directory.",
1496+
"Make this room visible in the public room directory.": "Make this room visible in the public room directory.",
14951497
"This room is in some spaces you're not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "This room is in some spaces you're not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.",
14961498
"This upgrade will allow members of selected spaces access to this room without an invite.": "This upgrade will allow members of selected spaces access to this room without an invite.",
14971499
"Messages containing keywords": "Messages containing keywords",
@@ -2767,7 +2769,6 @@
27672769
"Anyone will be able to find and join this room.": "Anyone will be able to find and join this room.",
27682770
"Only people invited will be able to find and join this room.": "Only people invited will be able to find and join this room.",
27692771
"Anyone can request to join, but admins or moderators need to grant access. You can change this later.": "Anyone can request to join, but admins or moderators need to grant access. You can change this later.",
2770-
"Make this room visible in the public room directory.": "Make this room visible in the public room directory.",
27712772
"You can't disable this later. The room will be encrypted but the embedded call will not.": "You can't disable this later. The room will be encrypted but the embedded call will not.",
27722773
"You can't disable this later. Bridges & most bots won't work yet.": "You can't disable this later. Bridges & most bots won't work yet.",
27732774
"Your server requires encryption to be enabled in private rooms.": "Your server requires encryption to be enabled in private rooms.",

test/components/views/settings/JoinRuleSettings-test.tsx

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ limitations under the License.
1515
*/
1616

1717
import React from "react";
18-
import { fireEvent, render, screen, within } from "@testing-library/react";
18+
import { act, fireEvent, render, screen, within } from "@testing-library/react";
1919
import {
2020
EventType,
2121
GuestAccess,
@@ -25,6 +25,8 @@ import {
2525
Room,
2626
ClientEvent,
2727
RoomMember,
28+
MatrixError,
29+
Visibility,
2830
} from "matrix-js-sdk/src/matrix";
2931
import { defer, IDeferred } from "matrix-js-sdk/src/utils";
3032

@@ -51,6 +53,8 @@ describe("<JoinRuleSettings />", () => {
5153
getProfileInfo: jest.fn(),
5254
invite: jest.fn().mockResolvedValue(undefined),
5355
isRoomEncrypted: jest.fn().mockReturnValue(false),
56+
getRoomDirectoryVisibility: jest.fn(),
57+
setRoomDirectoryVisibility: jest.fn(),
5458
});
5559
const roomId = "!room:server.org";
5660
const newRoomId = "!roomUpgraded:server.org";
@@ -270,10 +274,77 @@ describe("<JoinRuleSettings />", () => {
270274
});
271275
});
272276

277+
describe("knock rooms directory visibility", () => {
278+
const getCheckbox = () => screen.getByRole("checkbox");
279+
let room: Room;
280+
281+
beforeEach(() => (room = new Room(roomId, client, userId)));
282+
283+
describe("when join rule is knock", () => {
284+
beforeEach(() => setRoomStateEvents(room, PreferredRoomVersions.KnockRooms, JoinRule.Knock));
285+
286+
it("should set the visibility to public", async () => {
287+
jest.spyOn(client, "getRoomDirectoryVisibility").mockResolvedValue({ visibility: Visibility.Private });
288+
jest.spyOn(client, "setRoomDirectoryVisibility").mockResolvedValue({});
289+
getComponent({ room });
290+
fireEvent.click(getCheckbox());
291+
await act(async () => await flushPromises());
292+
expect(client.setRoomDirectoryVisibility).toHaveBeenCalledWith(roomId, Visibility.Public);
293+
expect(getCheckbox()).toBeChecked();
294+
});
295+
296+
it("should set the visibility to private", async () => {
297+
jest.spyOn(client, "getRoomDirectoryVisibility").mockResolvedValue({ visibility: Visibility.Public });
298+
jest.spyOn(client, "setRoomDirectoryVisibility").mockResolvedValue({});
299+
getComponent({ room });
300+
await act(async () => await flushPromises());
301+
fireEvent.click(getCheckbox());
302+
await act(async () => await flushPromises());
303+
expect(client.setRoomDirectoryVisibility).toHaveBeenCalledWith(roomId, Visibility.Private);
304+
expect(getCheckbox()).not.toBeChecked();
305+
});
306+
307+
it("should call onError if setting visibility fails", async () => {
308+
const error = new MatrixError();
309+
jest.spyOn(client, "getRoomDirectoryVisibility").mockResolvedValue({ visibility: Visibility.Private });
310+
jest.spyOn(client, "setRoomDirectoryVisibility").mockRejectedValue(error);
311+
getComponent({ room });
312+
fireEvent.click(getCheckbox());
313+
await act(async () => await flushPromises());
314+
expect(getCheckbox()).not.toBeChecked();
315+
expect(defaultProps.onError).toHaveBeenCalledWith(error);
316+
});
317+
});
318+
319+
describe("when the room version is unsupported and upgrade is enabled", () => {
320+
it("should disable the checkbox", () => {
321+
setRoomStateEvents(room, "6", JoinRule.Invite);
322+
getComponent({ promptUpgrade: true, room });
323+
expect(getCheckbox()).toBeDisabled();
324+
});
325+
});
326+
327+
describe("when join rule is not knock", () => {
328+
beforeEach(() => {
329+
setRoomStateEvents(room, PreferredRoomVersions.KnockRooms, JoinRule.Invite);
330+
getComponent({ room });
331+
});
332+
333+
it("should disable the checkbox", () => {
334+
expect(getCheckbox()).toBeDisabled();
335+
});
336+
337+
it("should set the visibility to private by default", () => {
338+
expect(getCheckbox()).not.toBeChecked();
339+
});
340+
});
341+
});
342+
273343
it("should not show knock room join rule", async () => {
274344
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);
275345
const room = new Room(newRoomId, client, userId);
276-
getComponent({ room: room });
346+
setRoomStateEvents(room, PreferredRoomVersions.KnockRooms);
347+
getComponent({ room });
277348
expect(screen.queryByText("Ask to join")).not.toBeInTheDocument();
278349
});
279350
});

0 commit comments

Comments
 (0)