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

Commit 53b42e3

Browse files
authored
Show room options menu if "UIComponent.roomOptionsMenu" is enabled (#10365)
* Show room options menu if "UIComponent.roomOptionsMenu" is enabled Signed-off-by: Mikhail Aheichyk <[email protected]> * Explicit type is removed. Signed-off-by: Mikhail Aheichyk <[email protected]> --------- Signed-off-by: Mikhail Aheichyk <[email protected]> Co-authored-by: Mikhail Aheichyk <[email protected]>
1 parent 53415bf commit 53b42e3

File tree

7 files changed

+143
-29
lines changed

7 files changed

+143
-29
lines changed

src/components/views/dialogs/spotlight/RoomResultContextMenus.tsx

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import { RoomNotificationContextMenu } from "../../context_menus/RoomNotificatio
2727
import SpaceContextMenu from "../../context_menus/SpaceContextMenu";
2828
import { ButtonEvent } from "../../elements/AccessibleButton";
2929
import { contextMenuBelow } from "../../rooms/RoomTile";
30+
import { shouldShowComponent } from "../../../../customisations/helpers/UIComponents";
31+
import { UIComponent } from "../../../../settings/UIFeature";
3032

3133
interface Props {
3234
room: Room;
@@ -80,18 +82,20 @@ export function RoomResultContextMenus({ room }: Props): JSX.Element {
8082

8183
return (
8284
<Fragment>
83-
<ContextMenuTooltipButton
84-
className="mx_SpotlightDialog_option--menu"
85-
onClick={(ev: ButtonEvent) => {
86-
ev.preventDefault();
87-
ev.stopPropagation();
85+
{shouldShowComponent(UIComponent.RoomOptionsMenu) && (
86+
<ContextMenuTooltipButton
87+
className="mx_SpotlightDialog_option--menu"
88+
onClick={(ev: ButtonEvent) => {
89+
ev.preventDefault();
90+
ev.stopPropagation();
8891

89-
const target = ev.target as HTMLElement;
90-
setGeneralMenuPosition(target.getBoundingClientRect());
91-
}}
92-
title={room.isSpaceRoom() ? _t("Space options") : _t("Room options")}
93-
isExpanded={generalMenuPosition !== null}
94-
/>
92+
const target = ev.target as HTMLElement;
93+
setGeneralMenuPosition(target.getBoundingClientRect());
94+
}}
95+
title={room.isSpaceRoom() ? _t("Space options") : _t("Room options")}
96+
isExpanded={generalMenuPosition !== null}
97+
/>
98+
)}
9599
{!room.isSpaceRoom() && (
96100
<ContextMenuTooltipButton
97101
className={notificationMenuClasses}

src/components/views/rooms/RoomHeader.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
6969
import { GroupCallDuration } from "../voip/CallDuration";
7070
import { Alignment } from "../elements/Tooltip";
7171
import RoomCallBanner from "../beacon/RoomCallBanner";
72+
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
73+
import { UIComponent } from "../../../settings/UIFeature";
7274

7375
class DisabledWithReason {
7476
public constructor(public readonly reason: string) {}
@@ -697,7 +699,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
697699
</RoomName>
698700
);
699701

700-
if (this.props.enableRoomOptionsMenu) {
702+
if (this.props.enableRoomOptionsMenu && shouldShowComponent(UIComponent.RoomOptionsMenu)) {
701703
return (
702704
<ContextMenuTooltipButton
703705
className="mx_RoomHeader_name"

src/components/views/rooms/RoomTile.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ import { CallStore, CallStoreEvent } from "../../../stores/CallStore";
4949
import { SdkContextClass } from "../../../contexts/SDKContext";
5050
import { useHasRoomLiveVoiceBroadcast } from "../../../voice-broadcast";
5151
import { RoomTileSubtitle } from "./RoomTileSubtitle";
52+
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
53+
import { UIComponent } from "../../../settings/UIFeature";
5254

5355
interface Props {
5456
room: Room;
@@ -118,7 +120,7 @@ export class RoomTile extends React.PureComponent<ClassProps, State> {
118120
};
119121

120122
private get showContextMenu(): boolean {
121-
return this.props.tag !== DefaultTagID.Invite;
123+
return this.props.tag !== DefaultTagID.Invite && shouldShowComponent(UIComponent.RoomOptionsMenu);
122124
}
123125

124126
private get showMessagePreview(): boolean {

src/settings/UIFeature.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,9 @@ export enum UIComponent {
7070
* Component that lead to the user being able to search, dial, explore rooms
7171
*/
7272
FilterContainer = "UIComponent.filterContainer",
73+
74+
/**
75+
* Components that lead the user to room options menu.
76+
*/
77+
RoomOptionsMenu = "UIComponent.roomOptionsMenu",
7378
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
Copyright 2023 Mikhail Aheichyk
3+
Copyright 2023 Nordeck IT + Consulting GmbH.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
import React from "react";
19+
import { render, screen, RenderResult } from "@testing-library/react";
20+
import { mocked } from "jest-mock";
21+
import { Room } from "matrix-js-sdk/src/models/room";
22+
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
23+
24+
import { RoomResultContextMenus } from "../../../../../src/components/views/dialogs/spotlight/RoomResultContextMenus";
25+
import { filterConsole, stubClient } from "../../../../test-utils";
26+
import { shouldShowComponent } from "../../../../../src/customisations/helpers/UIComponents";
27+
import { UIComponent } from "../../../../../src/settings/UIFeature";
28+
29+
jest.mock("../../../../../src/customisations/helpers/UIComponents", () => ({
30+
shouldShowComponent: jest.fn(),
31+
}));
32+
33+
describe("RoomResultContextMenus", () => {
34+
let client: MatrixClient;
35+
let room: Room;
36+
37+
const renderRoomResultContextMenus = (): RenderResult => {
38+
return render(<RoomResultContextMenus room={room} />);
39+
};
40+
41+
filterConsole(
42+
// irrelevant for this test
43+
"Room !1:example.org does not have an m.room.create event",
44+
);
45+
46+
beforeEach(() => {
47+
client = stubClient();
48+
room = new Room("!1:example.org", client, "@alice:example.org", {
49+
pendingEventOrdering: PendingEventOrdering.Detached,
50+
});
51+
});
52+
53+
it("does not render the room options context menu when UIComponent customisations disable room options", () => {
54+
mocked(shouldShowComponent).mockReturnValue(false);
55+
renderRoomResultContextMenus();
56+
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.RoomOptionsMenu);
57+
expect(screen.queryByRole("button", { name: "Room options" })).not.toBeInTheDocument();
58+
});
59+
60+
it("renders the room options context menu when UIComponent customisations enable room options", () => {
61+
mocked(shouldShowComponent).mockReturnValue(true);
62+
renderRoomResultContextMenus();
63+
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.RoomOptionsMenu);
64+
expect(screen.queryByRole("button", { name: "Room options" })).toBeInTheDocument();
65+
});
66+
});

test/components/views/rooms/RoomHeader-test.tsx

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ import { WidgetMessagingStore } from "../../../../src/stores/widgets/WidgetMessa
5757
import WidgetUtils from "../../../../src/utils/WidgetUtils";
5858
import { ElementWidgetActions } from "../../../../src/stores/widgets/ElementWidgetActions";
5959
import MediaDeviceHandler, { MediaDeviceKindEnum } from "../../../../src/MediaDeviceHandler";
60+
import { shouldShowComponent } from "../../../../src/customisations/helpers/UIComponents";
61+
import { UIComponent } from "../../../../src/settings/UIFeature";
62+
63+
jest.mock("../../../../src/customisations/helpers/UIComponents", () => ({
64+
shouldShowComponent: jest.fn(),
65+
}));
6066

6167
describe("RoomHeader", () => {
6268
let client: Mocked<MatrixClient>;
@@ -729,17 +735,26 @@ describe("RoomHeader", () => {
729735
expect(wrapper.container.querySelector(".mx_RoomHeader_button")).toBeFalsy();
730736
});
731737

732-
it("should render the room options context menu if not passing enableRoomOptionsMenu (default true)", () => {
738+
it("should render the room options context menu if not passing enableRoomOptionsMenu (default true) and UIComponent customisations room options enabled", () => {
739+
mocked(shouldShowComponent).mockReturnValue(true);
733740
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
734741
const wrapper = mountHeader(room);
742+
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.RoomOptionsMenu);
735743
expect(wrapper.container.querySelector(".mx_RoomHeader_name.mx_AccessibleButton")).toBeDefined();
736744
});
737745

738-
it("should not render the room options context menu if passing enableRoomOptionsMenu = false", () => {
739-
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
740-
const wrapper = mountHeader(room, { enableRoomOptionsMenu: false });
741-
expect(wrapper.container.querySelector(".mx_RoomHeader_name.mx_AccessibleButton")).toBeFalsy();
742-
});
746+
it.each([
747+
[false, true],
748+
[true, false],
749+
])(
750+
"should not render the room options context menu if passing enableRoomOptionsMenu = %s and UIComponent customisations room options enable = %s",
751+
(enableRoomOptionsMenu, showRoomOptionsMenu) => {
752+
mocked(shouldShowComponent).mockReturnValue(showRoomOptionsMenu);
753+
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
754+
const wrapper = mountHeader(room, { enableRoomOptionsMenu });
755+
expect(wrapper.container.querySelector(".mx_RoomHeader_name.mx_AccessibleButton")).toBeFalsy();
756+
},
757+
);
743758
});
744759

745760
interface IRoomCreationInfo {

test/components/views/rooms/RoomTile-test.tsx

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,14 @@ import { VoiceBroadcastInfoState } from "../../../../src/voice-broadcast";
4747
import { mkVoiceBroadcastInfoStateEvent } from "../../../voice-broadcast/utils/test-utils";
4848
import { TestSdkContext } from "../../../TestSdkContext";
4949
import { SDKContext } from "../../../../src/contexts/SDKContext";
50+
import { shouldShowComponent } from "../../../../src/customisations/helpers/UIComponents";
51+
import { UIComponent } from "../../../../src/settings/UIFeature";
5052
import { MessagePreviewStore } from "../../../../src/stores/room-list/MessagePreviewStore";
5153

54+
jest.mock("../../../../src/customisations/helpers/UIComponents", () => ({
55+
shouldShowComponent: jest.fn(),
56+
}));
57+
5258
describe("RoomTile", () => {
5359
jest.spyOn(PlatformPeg, "get").mockReturnValue({
5460
overrideBrowserShortcuts: () => false,
@@ -69,8 +75,8 @@ describe("RoomTile", () => {
6975
});
7076
};
7177

72-
const renderRoomTile = (): void => {
73-
renderResult = render(
78+
const renderRoomTile = (): RenderResult => {
79+
return render(
7480
<SDKContext.Provider value={sdkContext}>
7581
<RoomTile
7682
room={room}
@@ -85,7 +91,6 @@ describe("RoomTile", () => {
8591
let client: Mocked<MatrixClient>;
8692
let voiceBroadcastInfoEvent: MatrixEvent;
8793
let room: Room;
88-
let renderResult: RenderResult;
8994
let sdkContext: TestSdkContext;
9095
let showMessagePreview = false;
9196

@@ -148,12 +153,24 @@ describe("RoomTile", () => {
148153
});
149154

150155
describe("when message previews are not enabled", () => {
151-
beforeEach(() => {
156+
it("should render the room", () => {
157+
mocked(shouldShowComponent).mockReturnValue(true);
158+
const renderResult = renderRoomTile();
159+
expect(renderResult.container).toMatchSnapshot();
160+
});
161+
162+
it("does not render the room options context menu when UIComponent customisations disable room options", () => {
163+
mocked(shouldShowComponent).mockReturnValue(false);
152164
renderRoomTile();
165+
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.RoomOptionsMenu);
166+
expect(screen.queryByRole("button", { name: "Room options" })).not.toBeInTheDocument();
153167
});
154168

155-
it("should render the room", () => {
156-
expect(renderResult.container).toMatchSnapshot();
169+
it("renders the room options context menu when UIComponent customisations enable room options", () => {
170+
mocked(shouldShowComponent).mockReturnValue(true);
171+
renderRoomTile();
172+
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.RoomOptionsMenu);
173+
expect(screen.queryByRole("button", { name: "Room options" })).toBeInTheDocument();
157174
});
158175

159176
describe("when a call starts", () => {
@@ -176,13 +193,13 @@ describe("RoomTile", () => {
176193
});
177194

178195
afterEach(() => {
179-
renderResult.unmount();
180196
call.destroy();
181197
client.reEmitter.stopReEmitting(room, [RoomStateEvent.Events]);
182198
WidgetMessagingStore.instance.stopMessaging(widget, room.roomId);
183199
});
184200

185201
it("tracks connection state", async () => {
202+
renderRoomTile();
186203
screen.getByText("Video");
187204

188205
// Insert an await point in the connection method so we can inspect
@@ -205,6 +222,7 @@ describe("RoomTile", () => {
205222
});
206223

207224
it("tracks participants", () => {
225+
renderRoomTile();
208226
const alice: [RoomMember, Set<string>] = [
209227
mkRoomMember(room.roomId, "@alice:example.org"),
210228
new Set(["a"]),
@@ -238,6 +256,7 @@ describe("RoomTile", () => {
238256

239257
describe("and a live broadcast starts", () => {
240258
beforeEach(async () => {
259+
renderRoomTile();
241260
await setUpVoiceBroadcast(VoiceBroadcastInfoState.Started);
242261
});
243262

@@ -250,6 +269,7 @@ describe("RoomTile", () => {
250269

251270
describe("when a live voice broadcast starts", () => {
252271
beforeEach(async () => {
272+
renderRoomTile();
253273
await setUpVoiceBroadcast(VoiceBroadcastInfoState.Started);
254274
});
255275

@@ -285,7 +305,7 @@ describe("RoomTile", () => {
285305
});
286306

287307
it("should render a room without a message as expected", async () => {
288-
renderRoomTile();
308+
const renderResult = renderRoomTile();
289309
// flush promises here because the preview is created asynchronously
290310
await flushPromises();
291311
expect(renderResult.asFragment()).toMatchSnapshot();
@@ -297,7 +317,7 @@ describe("RoomTile", () => {
297317
});
298318

299319
it("should render as expected", async () => {
300-
renderRoomTile();
320+
const renderResult = renderRoomTile();
301321
expect(await screen.findByText("test message")).toBeInTheDocument();
302322
expect(renderResult.asFragment()).toMatchSnapshot();
303323
});
@@ -309,7 +329,7 @@ describe("RoomTile", () => {
309329
});
310330

311331
it("should render as expected", async () => {
312-
renderRoomTile();
332+
const renderResult = renderRoomTile();
313333
expect(await screen.findByText("test thread reply")).toBeInTheDocument();
314334
expect(renderResult.asFragment()).toMatchSnapshot();
315335
});

0 commit comments

Comments
 (0)