Skip to content

Commit 7d94fa9

Browse files
authored
New room list: add compose menu for spaces in header (#29347)
* 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
1 parent 37136ec commit 7d94fa9

File tree

3 files changed

+49
-18
lines changed

3 files changed

+49
-18
lines changed

playwright/e2e/left-panel/room-list-view/room-list-header.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@ test.describe("Header section of the room list", () => {
5353

5454
const roomListHeader = getHeaderSection(page);
5555
await expect(roomListHeader.getByRole("heading", { name: "MySpace" })).toBeVisible();
56-
await expect(roomListHeader.getByRole("button", { name: "Add" })).not.toBeVisible();
56+
await expect(roomListHeader.getByRole("button", { name: "Add" })).toBeVisible();
5757
});
5858
});

src/components/viewmodels/roomlist/RoomListHeaderViewModel.tsx

+23-14
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
UPDATE_SELECTED_SPACE,
2424
} from "../../../stores/spaces";
2525
import SpaceStore from "../../../stores/spaces/SpaceStore";
26+
import { showCreateNewRoom } from "../../../utils/space";
2627

2728
/**
2829
* Hook to get the active space and its title.
@@ -55,7 +56,7 @@ export interface RoomListHeaderViewState {
5556
title: string;
5657
/**
5758
* Whether to display the compose menu
58-
* True if the user can create rooms and is not in a Space
59+
* True if the user can create rooms
5960
*/
6061
displayComposeMenu: boolean;
6162
/**
@@ -84,15 +85,13 @@ export interface RoomListHeaderViewState {
8485

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

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

9796
/* Actions */
9897

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

104-
const createRoom = useCallback((e: Event) => {
105-
defaultDispatcher.fire(Action.CreateRoom);
106-
PosthogTrackers.trackInteraction("WebRoomListHeaderPlusMenuCreateRoomItem", e);
107-
}, []);
103+
const createRoom = useCallback(
104+
(e: Event) => {
105+
if (activeSpace) {
106+
showCreateNewRoom(activeSpace);
107+
} else {
108+
defaultDispatcher.fire(Action.CreateRoom);
109+
}
110+
PosthogTrackers.trackInteraction("WebRoomListHeaderPlusMenuCreateRoomItem", e);
111+
},
112+
[activeSpace],
113+
);
108114

109115
const elementCallVideoRoomsEnabled = useFeatureEnabled("feature_element_call_video_rooms");
110-
const createVideoRoom = useCallback(
111-
() =>
116+
const createVideoRoom = useCallback(() => {
117+
const type = elementCallVideoRoomsEnabled ? RoomType.UnstableCall : RoomType.ElementVideo;
118+
if (activeSpace) {
119+
showCreateNewRoom(activeSpace, type);
120+
} else {
112121
defaultDispatcher.dispatch({
113122
action: Action.CreateRoom,
114-
type: elementCallVideoRoomsEnabled ? RoomType.UnstableCall : RoomType.ElementVideo,
115-
}),
116-
[elementCallVideoRoomsEnabled],
117-
);
123+
type,
124+
});
125+
}
126+
}, [activeSpace, elementCallVideoRoomsEnabled]);
118127

119128
return {
120129
title,

test/unit-tests/components/viewmodels/roomlist/RoomListHeaderViewModel-test.tsx

+25-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

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

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

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

25+
jest.mock("../../../../../src/utils/space", () => ({
26+
showCreateNewRoom: jest.fn(),
27+
}));
28+
2429
describe("useRoomListHeaderViewModel", () => {
2530
let matrixClient: MatrixClient;
31+
let space: Room;
2632

2733
beforeEach(() => {
2834
matrixClient = stubClient();
35+
space = mkStubRoom("spaceId", "spaceName", matrixClient);
2936
});
3037

3138
afterEach(() => {
@@ -39,8 +46,7 @@ describe("useRoomListHeaderViewModel", () => {
3946
});
4047

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

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

90+
it("should call showCreateNewRoom when createRoom is called in a space", () => {
91+
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
92+
const { result } = renderHook(() => useRoomListHeaderViewModel());
93+
result.current.createRoom(new Event("click"));
94+
95+
expect(showCreateNewRoom).toHaveBeenCalledWith(space);
96+
});
97+
8498
it("should fire Action.CreateRoom with RoomType.UnstableCall when createVideoRoom is called and feature_element_call_video_rooms is enabled", () => {
8599
jest.spyOn(SettingsStore, "getValue").mockReturnValue(true);
86100
const spy = jest.spyOn(defaultDispatcher, "dispatch");
@@ -98,4 +112,12 @@ describe("useRoomListHeaderViewModel", () => {
98112

99113
expect(spy).toHaveBeenCalledWith({ action: Action.CreateRoom, type: RoomType.ElementVideo });
100114
});
115+
116+
it("should call showCreateNewRoom when createVideoRoom is called in a space", () => {
117+
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
118+
const { result } = renderHook(() => useRoomListHeaderViewModel());
119+
result.current.createVideoRoom();
120+
121+
expect(showCreateNewRoom).toHaveBeenCalledWith(space, RoomType.ElementVideo);
122+
});
101123
});

0 commit comments

Comments
 (0)