Show room options menu if "UIComponent.roomOptionsMenu" is enabled (#10365)
* Show room options menu if "UIComponent.roomOptionsMenu" is enabled Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net> * Explicit type is removed. Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net> --------- Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net> Co-authored-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net>
This commit is contained in:
parent
53415bfdfe
commit
53b42e3217
7 changed files with 144 additions and 30 deletions
|
@ -27,6 +27,8 @@ import { RoomNotificationContextMenu } from "../../context_menus/RoomNotificatio
|
|||
import SpaceContextMenu from "../../context_menus/SpaceContextMenu";
|
||||
import { ButtonEvent } from "../../elements/AccessibleButton";
|
||||
import { contextMenuBelow } from "../../rooms/RoomTile";
|
||||
import { shouldShowComponent } from "../../../../customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../../settings/UIFeature";
|
||||
|
||||
interface Props {
|
||||
room: Room;
|
||||
|
@ -80,18 +82,20 @@ export function RoomResultContextMenus({ room }: Props): JSX.Element {
|
|||
|
||||
return (
|
||||
<Fragment>
|
||||
<ContextMenuTooltipButton
|
||||
className="mx_SpotlightDialog_option--menu"
|
||||
onClick={(ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
{shouldShowComponent(UIComponent.RoomOptionsMenu) && (
|
||||
<ContextMenuTooltipButton
|
||||
className="mx_SpotlightDialog_option--menu"
|
||||
onClick={(ev: ButtonEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
const target = ev.target as HTMLElement;
|
||||
setGeneralMenuPosition(target.getBoundingClientRect());
|
||||
}}
|
||||
title={room.isSpaceRoom() ? _t("Space options") : _t("Room options")}
|
||||
isExpanded={generalMenuPosition !== null}
|
||||
/>
|
||||
const target = ev.target as HTMLElement;
|
||||
setGeneralMenuPosition(target.getBoundingClientRect());
|
||||
}}
|
||||
title={room.isSpaceRoom() ? _t("Space options") : _t("Room options")}
|
||||
isExpanded={generalMenuPosition !== null}
|
||||
/>
|
||||
)}
|
||||
{!room.isSpaceRoom() && (
|
||||
<ContextMenuTooltipButton
|
||||
className={notificationMenuClasses}
|
||||
|
|
|
@ -69,6 +69,8 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
|||
import { GroupCallDuration } from "../voip/CallDuration";
|
||||
import { Alignment } from "../elements/Tooltip";
|
||||
import RoomCallBanner from "../beacon/RoomCallBanner";
|
||||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../settings/UIFeature";
|
||||
|
||||
class DisabledWithReason {
|
||||
public constructor(public readonly reason: string) {}
|
||||
|
@ -697,7 +699,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
|
|||
</RoomName>
|
||||
);
|
||||
|
||||
if (this.props.enableRoomOptionsMenu) {
|
||||
if (this.props.enableRoomOptionsMenu && shouldShowComponent(UIComponent.RoomOptionsMenu)) {
|
||||
return (
|
||||
<ContextMenuTooltipButton
|
||||
className="mx_RoomHeader_name"
|
||||
|
|
|
@ -49,6 +49,8 @@ import { CallStore, CallStoreEvent } from "../../../stores/CallStore";
|
|||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
||||
import { useHasRoomLiveVoiceBroadcast } from "../../../voice-broadcast";
|
||||
import { RoomTileSubtitle } from "./RoomTileSubtitle";
|
||||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../settings/UIFeature";
|
||||
|
||||
interface Props {
|
||||
room: Room;
|
||||
|
@ -118,7 +120,7 @@ export class RoomTile extends React.PureComponent<ClassProps, State> {
|
|||
};
|
||||
|
||||
private get showContextMenu(): boolean {
|
||||
return this.props.tag !== DefaultTagID.Invite;
|
||||
return this.props.tag !== DefaultTagID.Invite && shouldShowComponent(UIComponent.RoomOptionsMenu);
|
||||
}
|
||||
|
||||
private get showMessagePreview(): boolean {
|
||||
|
|
|
@ -70,4 +70,9 @@ export enum UIComponent {
|
|||
* Component that lead to the user being able to search, dial, explore rooms
|
||||
*/
|
||||
FilterContainer = "UIComponent.filterContainer",
|
||||
|
||||
/**
|
||||
* Components that lead the user to room options menu.
|
||||
*/
|
||||
RoomOptionsMenu = "UIComponent.roomOptionsMenu",
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
Copyright 2023 Mikhail Aheichyk
|
||||
Copyright 2023 Nordeck IT + Consulting GmbH.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render, screen, RenderResult } from "@testing-library/react";
|
||||
import { mocked } from "jest-mock";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
|
||||
|
||||
import { RoomResultContextMenus } from "../../../../../src/components/views/dialogs/spotlight/RoomResultContextMenus";
|
||||
import { filterConsole, stubClient } from "../../../../test-utils";
|
||||
import { shouldShowComponent } from "../../../../../src/customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../../../src/settings/UIFeature";
|
||||
|
||||
jest.mock("../../../../../src/customisations/helpers/UIComponents", () => ({
|
||||
shouldShowComponent: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("RoomResultContextMenus", () => {
|
||||
let client: MatrixClient;
|
||||
let room: Room;
|
||||
|
||||
const renderRoomResultContextMenus = (): RenderResult => {
|
||||
return render(<RoomResultContextMenus room={room} />);
|
||||
};
|
||||
|
||||
filterConsole(
|
||||
// irrelevant for this test
|
||||
"Room !1:example.org does not have an m.room.create event",
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
client = stubClient();
|
||||
room = new Room("!1:example.org", client, "@alice:example.org", {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
});
|
||||
|
||||
it("does not render the room options context menu when UIComponent customisations disable room options", () => {
|
||||
mocked(shouldShowComponent).mockReturnValue(false);
|
||||
renderRoomResultContextMenus();
|
||||
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.RoomOptionsMenu);
|
||||
expect(screen.queryByRole("button", { name: "Room options" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the room options context menu when UIComponent customisations enable room options", () => {
|
||||
mocked(shouldShowComponent).mockReturnValue(true);
|
||||
renderRoomResultContextMenus();
|
||||
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.RoomOptionsMenu);
|
||||
expect(screen.queryByRole("button", { name: "Room options" })).toBeInTheDocument();
|
||||
});
|
||||
});
|
|
@ -57,6 +57,12 @@ import { WidgetMessagingStore } from "../../../../src/stores/widgets/WidgetMessa
|
|||
import WidgetUtils from "../../../../src/utils/WidgetUtils";
|
||||
import { ElementWidgetActions } from "../../../../src/stores/widgets/ElementWidgetActions";
|
||||
import MediaDeviceHandler, { MediaDeviceKindEnum } from "../../../../src/MediaDeviceHandler";
|
||||
import { shouldShowComponent } from "../../../../src/customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../../src/settings/UIFeature";
|
||||
|
||||
jest.mock("../../../../src/customisations/helpers/UIComponents", () => ({
|
||||
shouldShowComponent: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("RoomHeader", () => {
|
||||
let client: Mocked<MatrixClient>;
|
||||
|
@ -729,17 +735,26 @@ describe("RoomHeader", () => {
|
|||
expect(wrapper.container.querySelector(".mx_RoomHeader_button")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should render the room options context menu if not passing enableRoomOptionsMenu (default true)", () => {
|
||||
it("should render the room options context menu if not passing enableRoomOptionsMenu (default true) and UIComponent customisations room options enabled", () => {
|
||||
mocked(shouldShowComponent).mockReturnValue(true);
|
||||
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
|
||||
const wrapper = mountHeader(room);
|
||||
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.RoomOptionsMenu);
|
||||
expect(wrapper.container.querySelector(".mx_RoomHeader_name.mx_AccessibleButton")).toBeDefined();
|
||||
});
|
||||
|
||||
it("should not render the room options context menu if passing enableRoomOptionsMenu = false", () => {
|
||||
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
|
||||
const wrapper = mountHeader(room, { enableRoomOptionsMenu: false });
|
||||
expect(wrapper.container.querySelector(".mx_RoomHeader_name.mx_AccessibleButton")).toBeFalsy();
|
||||
});
|
||||
it.each([
|
||||
[false, true],
|
||||
[true, false],
|
||||
])(
|
||||
"should not render the room options context menu if passing enableRoomOptionsMenu = %s and UIComponent customisations room options enable = %s",
|
||||
(enableRoomOptionsMenu, showRoomOptionsMenu) => {
|
||||
mocked(shouldShowComponent).mockReturnValue(showRoomOptionsMenu);
|
||||
const room = createRoom({ name: "Room", isDm: false, userIds: [] });
|
||||
const wrapper = mountHeader(room, { enableRoomOptionsMenu });
|
||||
expect(wrapper.container.querySelector(".mx_RoomHeader_name.mx_AccessibleButton")).toBeFalsy();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
interface IRoomCreationInfo {
|
||||
|
|
|
@ -47,8 +47,14 @@ import { VoiceBroadcastInfoState } from "../../../../src/voice-broadcast";
|
|||
import { mkVoiceBroadcastInfoStateEvent } from "../../../voice-broadcast/utils/test-utils";
|
||||
import { TestSdkContext } from "../../../TestSdkContext";
|
||||
import { SDKContext } from "../../../../src/contexts/SDKContext";
|
||||
import { shouldShowComponent } from "../../../../src/customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../../src/settings/UIFeature";
|
||||
import { MessagePreviewStore } from "../../../../src/stores/room-list/MessagePreviewStore";
|
||||
|
||||
jest.mock("../../../../src/customisations/helpers/UIComponents", () => ({
|
||||
shouldShowComponent: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("RoomTile", () => {
|
||||
jest.spyOn(PlatformPeg, "get").mockReturnValue({
|
||||
overrideBrowserShortcuts: () => false,
|
||||
|
@ -69,8 +75,8 @@ describe("RoomTile", () => {
|
|||
});
|
||||
};
|
||||
|
||||
const renderRoomTile = (): void => {
|
||||
renderResult = render(
|
||||
const renderRoomTile = (): RenderResult => {
|
||||
return render(
|
||||
<SDKContext.Provider value={sdkContext}>
|
||||
<RoomTile
|
||||
room={room}
|
||||
|
@ -85,7 +91,6 @@ describe("RoomTile", () => {
|
|||
let client: Mocked<MatrixClient>;
|
||||
let voiceBroadcastInfoEvent: MatrixEvent;
|
||||
let room: Room;
|
||||
let renderResult: RenderResult;
|
||||
let sdkContext: TestSdkContext;
|
||||
let showMessagePreview = false;
|
||||
|
||||
|
@ -148,12 +153,24 @@ describe("RoomTile", () => {
|
|||
});
|
||||
|
||||
describe("when message previews are not enabled", () => {
|
||||
beforeEach(() => {
|
||||
renderRoomTile();
|
||||
it("should render the room", () => {
|
||||
mocked(shouldShowComponent).mockReturnValue(true);
|
||||
const renderResult = renderRoomTile();
|
||||
expect(renderResult.container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should render the room", () => {
|
||||
expect(renderResult.container).toMatchSnapshot();
|
||||
it("does not render the room options context menu when UIComponent customisations disable room options", () => {
|
||||
mocked(shouldShowComponent).mockReturnValue(false);
|
||||
renderRoomTile();
|
||||
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.RoomOptionsMenu);
|
||||
expect(screen.queryByRole("button", { name: "Room options" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the room options context menu when UIComponent customisations enable room options", () => {
|
||||
mocked(shouldShowComponent).mockReturnValue(true);
|
||||
renderRoomTile();
|
||||
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.RoomOptionsMenu);
|
||||
expect(screen.queryByRole("button", { name: "Room options" })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe("when a call starts", () => {
|
||||
|
@ -176,13 +193,13 @@ describe("RoomTile", () => {
|
|||
});
|
||||
|
||||
afterEach(() => {
|
||||
renderResult.unmount();
|
||||
call.destroy();
|
||||
client.reEmitter.stopReEmitting(room, [RoomStateEvent.Events]);
|
||||
WidgetMessagingStore.instance.stopMessaging(widget, room.roomId);
|
||||
});
|
||||
|
||||
it("tracks connection state", async () => {
|
||||
renderRoomTile();
|
||||
screen.getByText("Video");
|
||||
|
||||
// Insert an await point in the connection method so we can inspect
|
||||
|
@ -205,6 +222,7 @@ describe("RoomTile", () => {
|
|||
});
|
||||
|
||||
it("tracks participants", () => {
|
||||
renderRoomTile();
|
||||
const alice: [RoomMember, Set<string>] = [
|
||||
mkRoomMember(room.roomId, "@alice:example.org"),
|
||||
new Set(["a"]),
|
||||
|
@ -238,6 +256,7 @@ describe("RoomTile", () => {
|
|||
|
||||
describe("and a live broadcast starts", () => {
|
||||
beforeEach(async () => {
|
||||
renderRoomTile();
|
||||
await setUpVoiceBroadcast(VoiceBroadcastInfoState.Started);
|
||||
});
|
||||
|
||||
|
@ -250,6 +269,7 @@ describe("RoomTile", () => {
|
|||
|
||||
describe("when a live voice broadcast starts", () => {
|
||||
beforeEach(async () => {
|
||||
renderRoomTile();
|
||||
await setUpVoiceBroadcast(VoiceBroadcastInfoState.Started);
|
||||
});
|
||||
|
||||
|
@ -285,7 +305,7 @@ describe("RoomTile", () => {
|
|||
});
|
||||
|
||||
it("should render a room without a message as expected", async () => {
|
||||
renderRoomTile();
|
||||
const renderResult = renderRoomTile();
|
||||
// flush promises here because the preview is created asynchronously
|
||||
await flushPromises();
|
||||
expect(renderResult.asFragment()).toMatchSnapshot();
|
||||
|
@ -297,7 +317,7 @@ describe("RoomTile", () => {
|
|||
});
|
||||
|
||||
it("should render as expected", async () => {
|
||||
renderRoomTile();
|
||||
const renderResult = renderRoomTile();
|
||||
expect(await screen.findByText("test message")).toBeInTheDocument();
|
||||
expect(renderResult.asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
@ -309,7 +329,7 @@ describe("RoomTile", () => {
|
|||
});
|
||||
|
||||
it("should render as expected", async () => {
|
||||
renderRoomTile();
|
||||
const renderResult = renderRoomTile();
|
||||
expect(await screen.findByText("test thread reply")).toBeInTheDocument();
|
||||
expect(renderResult.asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue