Skip to content

Commit

Permalink
New room list: add compose menu for spaces in header (#29347)
Browse files Browse the repository at this point in the history
* feat(new room list): add compose menu in header for spaces

* test(new room list): add tests for space

* test(e2e new room list): update space test

* chore: formatting and reuse type var
  • Loading branch information
florianduros authored Feb 24, 2025
1 parent 37136ec commit 7d94fa9
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ test.describe("Header section of the room list", () => {

const roomListHeader = getHeaderSection(page);
await expect(roomListHeader.getByRole("heading", { name: "MySpace" })).toBeVisible();
await expect(roomListHeader.getByRole("button", { name: "Add" })).not.toBeVisible();
await expect(roomListHeader.getByRole("button", { name: "Add" })).toBeVisible();
});
});
37 changes: 23 additions & 14 deletions src/components/viewmodels/roomlist/RoomListHeaderViewModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
UPDATE_SELECTED_SPACE,
} from "../../../stores/spaces";
import SpaceStore from "../../../stores/spaces/SpaceStore";
import { showCreateNewRoom } from "../../../utils/space";

/**
* Hook to get the active space and its title.
Expand Down Expand Up @@ -55,7 +56,7 @@ export interface RoomListHeaderViewState {
title: string;
/**
* Whether to display the compose menu
* True if the user can create rooms and is not in a Space
* True if the user can create rooms
*/
displayComposeMenu: boolean;
/**
Expand Down Expand Up @@ -84,15 +85,13 @@ export interface RoomListHeaderViewState {

/**
* View model for the RoomListHeader.
* The actions don't work when called in a space yet.
*/
export function useRoomListHeaderViewModel(): RoomListHeaderViewState {
const { activeSpace, title } = useSpace();

const canCreateRoom = shouldShowComponent(UIComponent.CreateRooms);
const canCreateVideoRoom = useFeatureEnabled("feature_video_rooms");
// Temporary: don't display the compose menu when in a Space
const displayComposeMenu = canCreateRoom && !activeSpace;
const displayComposeMenu = canCreateRoom;

/* Actions */

Expand All @@ -101,20 +100,30 @@ export function useRoomListHeaderViewModel(): RoomListHeaderViewState {
PosthogTrackers.trackInteraction("WebRoomListHeaderPlusMenuCreateChatItem", e);
}, []);

const createRoom = useCallback((e: Event) => {
defaultDispatcher.fire(Action.CreateRoom);
PosthogTrackers.trackInteraction("WebRoomListHeaderPlusMenuCreateRoomItem", e);
}, []);
const createRoom = useCallback(
(e: Event) => {
if (activeSpace) {
showCreateNewRoom(activeSpace);
} else {
defaultDispatcher.fire(Action.CreateRoom);
}
PosthogTrackers.trackInteraction("WebRoomListHeaderPlusMenuCreateRoomItem", e);
},
[activeSpace],
);

const elementCallVideoRoomsEnabled = useFeatureEnabled("feature_element_call_video_rooms");
const createVideoRoom = useCallback(
() =>
const createVideoRoom = useCallback(() => {
const type = elementCallVideoRoomsEnabled ? RoomType.UnstableCall : RoomType.ElementVideo;
if (activeSpace) {
showCreateNewRoom(activeSpace, type);
} else {
defaultDispatcher.dispatch({
action: Action.CreateRoom,
type: elementCallVideoRoomsEnabled ? RoomType.UnstableCall : RoomType.ElementVideo,
}),
[elementCallVideoRoomsEnabled],
);
type,
});
}
}, [activeSpace, elementCallVideoRoomsEnabled]);

return {
title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { renderHook } from "jest-matrix-react";
import { type MatrixClient, RoomType } from "matrix-js-sdk/src/matrix";
import { type MatrixClient, type Room, RoomType } from "matrix-js-sdk/src/matrix";
import { mocked } from "jest-mock";

import { useRoomListHeaderViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListHeaderViewModel";
Expand All @@ -16,16 +16,23 @@ import { shouldShowComponent } from "../../../../../src/customisations/helpers/U
import SettingsStore from "../../../../../src/settings/SettingsStore";
import defaultDispatcher from "../../../../../src/dispatcher/dispatcher";
import { Action } from "../../../../../src/dispatcher/actions";
import { showCreateNewRoom } from "../../../../../src/utils/space";

jest.mock("../../../../../src/customisations/helpers/UIComponents", () => ({
shouldShowComponent: jest.fn(),
}));

jest.mock("../../../../../src/utils/space", () => ({
showCreateNewRoom: jest.fn(),
}));

describe("useRoomListHeaderViewModel", () => {
let matrixClient: MatrixClient;
let space: Room;

beforeEach(() => {
matrixClient = stubClient();
space = mkStubRoom("spaceId", "spaceName", matrixClient);
});

afterEach(() => {
Expand All @@ -39,8 +46,7 @@ describe("useRoomListHeaderViewModel", () => {
});

it("should return the current space name as title", () => {
const room = mkStubRoom("spaceId", "spaceName", matrixClient);
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(room);
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
const { result } = renderHook(() => useRoomListHeaderViewModel());

expect(result.current.title).toStrictEqual("spaceName");
Expand Down Expand Up @@ -81,6 +87,14 @@ describe("useRoomListHeaderViewModel", () => {
expect(spy).toHaveBeenCalledWith(Action.CreateRoom);
});

it("should call showCreateNewRoom when createRoom is called in a space", () => {
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
const { result } = renderHook(() => useRoomListHeaderViewModel());
result.current.createRoom(new Event("click"));

expect(showCreateNewRoom).toHaveBeenCalledWith(space);
});

it("should fire Action.CreateRoom with RoomType.UnstableCall when createVideoRoom is called and feature_element_call_video_rooms is enabled", () => {
jest.spyOn(SettingsStore, "getValue").mockReturnValue(true);
const spy = jest.spyOn(defaultDispatcher, "dispatch");
Expand All @@ -98,4 +112,12 @@ describe("useRoomListHeaderViewModel", () => {

expect(spy).toHaveBeenCalledWith({ action: Action.CreateRoom, type: RoomType.ElementVideo });
});

it("should call showCreateNewRoom when createVideoRoom is called in a space", () => {
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
const { result } = renderHook(() => useRoomListHeaderViewModel());
result.current.createVideoRoom();

expect(showCreateNewRoom).toHaveBeenCalledWith(space, RoomType.ElementVideo);
});
});

0 comments on commit 7d94fa9

Please sign in to comment.