diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index ac3c01f215..4b449708e5 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -165,6 +165,16 @@ interface IRoomProps extends RoomViewProps { * Omitting this will mean that RoomView renders for the room held in SDKContext.RoomViewStore. */ roomId?: string; + + /* + * If true, hide the header + */ + hideHeader?: boolean; + + /* + * If true, hide the composer + */ + hideComposer?: boolean; } export { MainSplitContentType }; @@ -2455,6 +2465,7 @@ export class RoomView extends React.Component { let messageComposer; const showComposer = + !this.props.hideComposer && !isRoomEncryptionLoading && // joined and not showing search results myMembership === KnownMembership.Join && @@ -2665,10 +2676,12 @@ export class RoomView extends React.Component { ref={this.roomViewBody} data-layout={this.state.layout} > - + {!this.props.hideHeader && ( + + )} {mainSplitBody} diff --git a/src/modules/BuiltinsApi.tsx b/src/modules/BuiltinsApi.tsx index b1225f56cb..9ede5ef99a 100644 --- a/src/modules/BuiltinsApi.tsx +++ b/src/modules/BuiltinsApi.tsx @@ -12,6 +12,9 @@ import { MatrixClientPeg } from "../MatrixClientPeg"; import type { Room } from "matrix-js-sdk/src/matrix"; interface RoomViewPropsWithRoomId extends RoomViewProps { + /** + * The ID of the room to display + */ roomId?: string; } @@ -26,9 +29,8 @@ interface Components { } export class ElementWebBuiltinsApi implements BuiltinsApi { - private _roomView?: React.ComponentType; - private _roomAvatar?: React.ComponentType; - + private _roomView?: Components["roomView"]; + private _roomAvatar?: Components["roomAvatar"]; /** * Sets the components used by the API. * @@ -59,9 +61,9 @@ export class ElementWebBuiltinsApi implements BuiltinsApi { return this._roomAvatar; } - public renderRoomView(roomId: string): React.ReactNode { + public renderRoomView(roomId: string, props?: RoomViewProps): React.ReactNode { const Component = this.getRoomViewComponent(); - return ; + return ; } public renderRoomAvatar(roomId: string, size?: string): React.ReactNode { diff --git a/test/unit-tests/components/structures/RoomView-test.tsx b/test/unit-tests/components/structures/RoomView-test.tsx index 7739022345..366512ddd5 100644 --- a/test/unit-tests/components/structures/RoomView-test.tsx +++ b/test/unit-tests/components/structures/RoomView-test.tsx @@ -75,7 +75,7 @@ import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; import { type ViewUserPayload } from "../../../../src/dispatcher/payloads/ViewUserPayload.ts"; import { CallStore } from "../../../../src/stores/CallStore.ts"; import MediaDeviceHandler, { MediaDeviceKindEnum } from "../../../../src/MediaDeviceHandler.ts"; -import Modal from "../../../../src/Modal.tsx"; +import Modal, { type ComponentProps } from "../../../../src/Modal.tsx"; import ErrorDialog from "../../../../src/components/views/dialogs/ErrorDialog.tsx"; // Used by group calls @@ -127,7 +127,10 @@ describe("RoomView", () => { cleanup(); }); - const mountRoomView = async (ref?: RefObject): Promise => { + const mountRoomView = async ( + ref?: RefObject, + props?: Partial>, + ): Promise => { if (stores.roomViewStore.getRoomId() !== room.roomId) { const switchedRoom = new Promise((resolve) => { const subFn = () => { @@ -159,6 +162,7 @@ describe("RoomView", () => { threepidInvite={undefined as any} forceTimeline={false} ref={ref} + {...props} /> , @@ -250,6 +254,25 @@ describe("RoomView", () => { expect(instance.getHiddenHighlightCount()).toBe(0); }); + it("should hide the composer when hideComposer=true", async () => { + // Join the room + jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join); + const { asFragment } = await mountRoomView(undefined, { hideComposer: true }); + + expect(screen.queryByRole("textbox", { name: "Send an unencrypted message…" })).not.toBeInTheDocument(); + expect(asFragment()).toMatchSnapshot(); + }); + + it("should hide the header when hideHeader=true", async () => { + // Join the room + jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join); + const { asFragment } = await mountRoomView(undefined, { hideHeader: true }); + + // Check that the room name button in the header is not rendered + expect(screen.queryByRole("button", { name: room.name })).not.toBeInTheDocument(); + expect(asFragment()).toMatchSnapshot(); + }); + describe("invites", () => { beforeEach(() => { const member = new RoomMember(room.roomId, cli.getSafeUserId()); diff --git a/test/unit-tests/components/structures/__snapshots__/RoomView-test.tsx.snap b/test/unit-tests/components/structures/__snapshots__/RoomView-test.tsx.snap index 5fc72fb6ef..dd3c06d6c1 100644 --- a/test/unit-tests/components/structures/__snapshots__/RoomView-test.tsx.snap +++ b/test/unit-tests/components/structures/__snapshots__/RoomView-test.tsx.snap @@ -363,7 +363,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] = > `; +exports[`RoomView should hide the composer when hideComposer=true 1`] = ` + +
+