diff --git a/playwright/e2e/left-panel/room-list-view/room-list-header.spec.ts b/playwright/e2e/left-panel/room-list-view/room-list-header.spec.ts index bda87b04621..2f4ef6f001d 100644 --- a/playwright/e2e/left-panel/room-list-view/room-list-header.spec.ts +++ b/playwright/e2e/left-panel/room-list-view/room-list-header.spec.ts @@ -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(); }); }); diff --git a/src/components/viewmodels/roomlist/RoomListHeaderViewModel.tsx b/src/components/viewmodels/roomlist/RoomListHeaderViewModel.tsx index 3284933a9b8..a37384b7fac 100644 --- a/src/components/viewmodels/roomlist/RoomListHeaderViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListHeaderViewModel.tsx @@ -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. @@ -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; /** @@ -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 */ @@ -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, diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListHeaderViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListHeaderViewModel-test.tsx index 95a594e3b65..fe96e268614 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListHeaderViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListHeaderViewModel-test.tsx @@ -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"; @@ -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(() => { @@ -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"); @@ -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"); @@ -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); + }); });