diff --git a/apps/web/src/viewmodels/room-list/RoomListHeaderViewModel.ts b/apps/web/src/viewmodels/room-list/RoomListHeaderViewModel.ts index fa7697d084..55626cb252 100644 --- a/apps/web/src/viewmodels/room-list/RoomListHeaderViewModel.ts +++ b/apps/web/src/viewmodels/room-list/RoomListHeaderViewModel.ts @@ -201,7 +201,7 @@ export class RoomListHeaderViewModel }; public createSection = (): void => { - // To be implemented when custom section creation is added in vms + RoomListStoreV3.instance.createSection(); }; } /** @@ -275,6 +275,10 @@ function computeHeaderSpaceState( ); const canAccessSpaceSettings = Boolean(activeSpace && shouldShowSpaceSettings(activeSpace)); + const isSectionFeatureEnabled = SettingsStore.getValue("feature_room_list_sections"); + const useComposeIcon = !isSectionFeatureEnabled; + const canCreateSection = isSectionFeatureEnabled; + return { title, canCreateRoom, @@ -283,8 +287,7 @@ function computeHeaderSpaceState( displaySpaceMenu, canInviteInSpace, canAccessSpaceSettings, - // To be implemented when custom section creation is added in vms - canCreateSection: false, - useComposeIcon: true, + canCreateSection, + useComposeIcon, }; } diff --git a/apps/web/src/viewmodels/room-list/RoomListItemViewModel.ts b/apps/web/src/viewmodels/room-list/RoomListItemViewModel.ts index ac3f32ad61..f40b60eebd 100644 --- a/apps/web/src/viewmodels/room-list/RoomListItemViewModel.ts +++ b/apps/web/src/viewmodels/room-list/RoomListItemViewModel.ts @@ -37,6 +37,7 @@ import { Action } from "../../dispatcher/actions"; import type { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"; import PosthogTrackers from "../../PosthogTrackers"; import { type Call, CallEvent } from "../../models/Call"; +import RoomListStoreV3 from "../../stores/room-list-v3/RoomListStoreV3"; interface RoomItemProps { room: Room; @@ -276,6 +277,8 @@ export class RoomListItemViewModel const callType = call?.callType === CallType.Voice ? "voice" : call?.callType === CallType.Video ? "video" : undefined; + const canMoveToSection = SettingsStore.getValue("feature_room_list_sections"); + return { id: room.roomId, room, @@ -303,8 +306,7 @@ export class RoomListItemViewModel canMarkAsRead, canMarkAsUnread, roomNotifState, - // To be implemented when custom section creation is added in vms - canMoveToSection: false, + canMoveToSection, }; } @@ -385,6 +387,6 @@ export class RoomListItemViewModel }; public onCreateSection = (): void => { - // To be implemented when custom section creation is added in vms + RoomListStoreV3.instance.createSection(); }; } diff --git a/apps/web/test/viewmodels/room-list/RoomListHeaderViewModel-test.ts b/apps/web/test/viewmodels/room-list/RoomListHeaderViewModel-test.ts index 936389603d..02a9cf787d 100644 --- a/apps/web/test/viewmodels/room-list/RoomListHeaderViewModel-test.ts +++ b/apps/web/test/viewmodels/room-list/RoomListHeaderViewModel-test.ts @@ -159,6 +159,23 @@ describe("RoomListHeaderViewModel", () => { vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance }); expect(vm.getSnapshot().isMessagePreviewEnabled).toBe(true); }); + + it.each([ + [true, true, false], + [false, false, true], + ])( + "when feature_room_list_sections is %s: canCreateSection=%s, useComposeIcon=%s", + (featureEnabled, expectedCanCreateSection, expectedUseComposeIcon) => { + jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => { + if (settingName === "feature_room_list_sections") return featureEnabled; + return false; + }); + + vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance }); + expect(vm.getSnapshot().canCreateSection).toBe(expectedCanCreateSection); + expect(vm.getSnapshot().useComposeIcon).toBe(expectedUseComposeIcon); + }, + ); }); describe("event listeners", () => { @@ -296,6 +313,13 @@ describe("RoomListHeaderViewModel", () => { ); }); + it("should call createSection on RoomListStoreV3 when createSection is called", () => { + const createSectionSpy = jest.spyOn(RoomListStoreV3.instance, "createSection").mockResolvedValue(); + vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance }); + vm.createSection(); + expect(createSectionSpy).toHaveBeenCalled(); + }); + it("should toggle message preview from enabled to disabled", () => { jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => { if (settingName === "RoomList.showMessagePreview") return true; diff --git a/apps/web/test/viewmodels/room-list/RoomListItemViewModel-test.tsx b/apps/web/test/viewmodels/room-list/RoomListItemViewModel-test.tsx index e3b349e085..398631271f 100644 --- a/apps/web/test/viewmodels/room-list/RoomListItemViewModel-test.tsx +++ b/apps/web/test/viewmodels/room-list/RoomListItemViewModel-test.tsx @@ -29,6 +29,7 @@ import { Action } from "../../../src/dispatcher/actions"; import { CallStore } from "../../../src/stores/CallStore"; import { CallEvent, type Call } from "../../../src/models/Call"; import { RoomListItemViewModel } from "../../../src/viewmodels/room-list/RoomListItemViewModel"; +import RoomListStoreV3 from "../../../src/stores/room-list-v3/RoomListStoreV3"; jest.mock("../../../src/viewmodels/room-list/utils", () => ({ hasAccessToOptionsMenu: jest.fn().mockReturnValue(true), @@ -501,6 +502,20 @@ describe("RoomListItemViewModel", () => { }); }); + describe("canMoveToSection", () => { + it.each([ + [true, true], + [false, false], + ])("should be %s when feature_room_list_sections is %s", (featureEnabled, expected) => { + jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => { + if (setting === "feature_room_list_sections") return featureEnabled; + return false; + }); + viewModel = new RoomListItemViewModel({ room, client: matrixClient }); + expect(viewModel.getSnapshot().canMoveToSection).toBe(expected); + }); + }); + describe("Actions", () => { it("should dispatch view room action on openRoom", () => { viewModel = new RoomListItemViewModel({ room, client: matrixClient }); @@ -572,6 +587,13 @@ describe("RoomListItemViewModel", () => { room_id: "!room:server", }); }); + + it("should call createSection on RoomListStoreV3 when onCreateSection is called", () => { + const createSectionSpy = jest.spyOn(RoomListStoreV3.instance, "createSection").mockResolvedValue(); + viewModel = new RoomListItemViewModel({ room, client: matrixClient }); + viewModel.onCreateSection(); + expect(createSectionSpy).toHaveBeenCalled(); + }); }); describe("Cleanup", () => {