Room list: add collapse/expand all sections (#33318)
* chore: update compound design tokens * feat(sc): add collapse/expand button to room list header * feat: add new events to broadcast section state * feat(vm): add expand/collpase event to room list events * test: add e2e tests * chore: fix company name in copyright * chore: use two differant actions for collapse/expand * Update apps/web/src/viewmodels/room-list/RoomListHeaderViewModel.ts Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> * test: fix existing tests --------- Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
co-authored by
Michael Telatynski
parent
a7ab72af11
commit
c2e5aa7adc
@@ -323,6 +323,89 @@ describe("RoomListHeaderViewModel", () => {
|
||||
expect(createSectionSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("collapseOrExpandSections", () => {
|
||||
it("should dispatch RoomListCollapseAllSections when collapseSections is not 'expand'", () => {
|
||||
const fireSpy = jest.spyOn(defaultDispatcher, "fire");
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
vm.collapseOrExpandSections();
|
||||
|
||||
expect(fireSpy).toHaveBeenCalledWith(Action.RoomListCollapseAllSections);
|
||||
});
|
||||
|
||||
it("should dispatch RoomListExpandAllSections when collapseSections is 'expand'", () => {
|
||||
const fireSpy = jest.spyOn(defaultDispatcher, "fire");
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
// Drive the VM into the "expand" state by simulating all sections collapsed
|
||||
defaultDispatcher.dispatch(
|
||||
{
|
||||
action: Action.RoomListSectionsCollapseStateChanged,
|
||||
collapseSections: "collapse",
|
||||
},
|
||||
true,
|
||||
);
|
||||
expect(vm.getSnapshot().collapseSections).toBe("expand");
|
||||
vm.collapseOrExpandSections();
|
||||
|
||||
expect(fireSpy).toHaveBeenCalledWith(Action.RoomListExpandAllSections);
|
||||
});
|
||||
});
|
||||
|
||||
describe("RoomListSectionsCollapseStateChanged handling", () => {
|
||||
it("should set collapseSections to 'expand' when collapseSections is collapse", () => {
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
defaultDispatcher.dispatch(
|
||||
{
|
||||
action: Action.RoomListSectionsCollapseStateChanged,
|
||||
collapseSections: "collapse",
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
expect(vm.getSnapshot().collapseSections).toBe("expand");
|
||||
});
|
||||
|
||||
it("should set collapseSections to 'collapse' when collapseSections is expand", () => {
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
defaultDispatcher.dispatch(
|
||||
{
|
||||
action: Action.RoomListSectionsCollapseStateChanged,
|
||||
collapseSections: "expand",
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
expect(vm.getSnapshot().collapseSections).toBe("collapse");
|
||||
});
|
||||
|
||||
it("should set collapseSections to undefined when collapseSections is undefined", () => {
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
// First drive it into a non-undefined state
|
||||
defaultDispatcher.dispatch(
|
||||
{
|
||||
action: Action.RoomListSectionsCollapseStateChanged,
|
||||
collapseSections: "collapse",
|
||||
},
|
||||
true,
|
||||
);
|
||||
expect(vm.getSnapshot().collapseSections).toBe("expand");
|
||||
|
||||
defaultDispatcher.dispatch(
|
||||
{
|
||||
action: Action.RoomListSectionsCollapseStateChanged,
|
||||
collapseSections: undefined,
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
expect(vm.getSnapshot().collapseSections).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
it("should toggle message preview from enabled to disabled", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
|
||||
if (settingName === "RoomList.showMessagePreview") return true;
|
||||
|
||||
@@ -465,6 +465,20 @@ describe("RoomListViewModel", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("notifyCollapseState", () => {
|
||||
it("should dispatch collapseSections=undefined when feature_room_list_sections is disabled", () => {
|
||||
viewModel = new RoomListViewModel({ client: matrixClient });
|
||||
|
||||
const dispatchSpy = jest.spyOn(dispatcher, "dispatch");
|
||||
RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate);
|
||||
|
||||
expect(dispatchSpy).toHaveBeenCalledWith({
|
||||
action: Action.RoomListSectionsCollapseStateChanged,
|
||||
collapseSections: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Keyboard navigation (ViewRoomDelta)", () => {
|
||||
beforeEach(() => {
|
||||
// stubClient sets up MatrixClientPeg which is needed when ViewRoom action is dispatched
|
||||
@@ -971,6 +985,96 @@ describe("RoomListViewModel", () => {
|
||||
expect(favSection!.roomIds).toEqual(["!fav1:server"]);
|
||||
});
|
||||
|
||||
describe("Collapse/expand all sections", () => {
|
||||
it("should collapse all sections when Action.RoomListCollapseAllSections is dispatched", async () => {
|
||||
viewModel = new RoomListViewModel({ client: matrixClient });
|
||||
|
||||
const favHeader = viewModel.getSectionHeaderViewModel(DefaultTagID.Favourite);
|
||||
const chatsHeader = viewModel.getSectionHeaderViewModel(CHATS_TAG);
|
||||
expect(favHeader.isExpanded).toBe(true);
|
||||
|
||||
dispatcher.dispatch({ action: Action.RoomListCollapseAllSections });
|
||||
await flushPromisesWithFakeTimers();
|
||||
|
||||
expect(favHeader.isExpanded).toBe(false);
|
||||
expect(chatsHeader.isExpanded).toBe(false);
|
||||
|
||||
const snapshot = viewModel.getSnapshot();
|
||||
expect(snapshot.sections.find((s) => s.id === DefaultTagID.Favourite)!.roomIds).toEqual([]);
|
||||
expect(snapshot.sections.find((s) => s.id === CHATS_TAG)!.roomIds).toEqual([]);
|
||||
});
|
||||
|
||||
it("should expand all sections when Action.RoomListExpandAllSections is dispatched", async () => {
|
||||
viewModel = new RoomListViewModel({ client: matrixClient });
|
||||
|
||||
// Collapse first
|
||||
const favHeader = viewModel.getSectionHeaderViewModel(DefaultTagID.Favourite);
|
||||
favHeader.onClick();
|
||||
expect(favHeader.isExpanded).toBe(false);
|
||||
|
||||
dispatcher.dispatch({ action: Action.RoomListExpandAllSections });
|
||||
await flushPromisesWithFakeTimers();
|
||||
|
||||
expect(favHeader.isExpanded).toBe(true);
|
||||
const snapshot = viewModel.getSnapshot();
|
||||
expect(snapshot.sections.find((s) => s.id === DefaultTagID.Favourite)!.roomIds).toEqual([
|
||||
"!fav1:server",
|
||||
"!fav2:server",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("notifyCollapseState", () => {
|
||||
it("should dispatch collapseSections=expand when all sections are expanded (default)", () => {
|
||||
viewModel = new RoomListViewModel({ client: matrixClient });
|
||||
|
||||
const dispatchSpy = jest.spyOn(dispatcher, "dispatch");
|
||||
RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate);
|
||||
|
||||
expect(dispatchSpy).toHaveBeenCalledWith({
|
||||
action: Action.RoomListSectionsCollapseStateChanged,
|
||||
collapseSections: "expand",
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch collapseSection=collapse when all sections are collapsed", () => {
|
||||
viewModel = new RoomListViewModel({ client: matrixClient });
|
||||
|
||||
// Collapse all sections
|
||||
viewModel.getSectionHeaderViewModel(DefaultTagID.Favourite).isExpanded = false;
|
||||
viewModel.getSectionHeaderViewModel(CHATS_TAG).isExpanded = false;
|
||||
viewModel.getSectionHeaderViewModel(DefaultTagID.LowPriority).isExpanded = false;
|
||||
|
||||
const dispatchSpy = jest.spyOn(dispatcher, "dispatch");
|
||||
RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate);
|
||||
|
||||
expect(dispatchSpy).toHaveBeenCalledWith({
|
||||
action: Action.RoomListSectionsCollapseStateChanged,
|
||||
collapseSections: "collapse",
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch collapseSection=undefined when it is a flat list", () => {
|
||||
jest.spyOn(RoomListStoreV3.instance, "getSortedRoomsInActiveSpace").mockReturnValue({
|
||||
spaceId: "home",
|
||||
sections: [
|
||||
{ tag: DefaultTagID.Favourite, rooms: [] },
|
||||
{ tag: CHATS_TAG, rooms: [regularRoom1] },
|
||||
{ tag: DefaultTagID.LowPriority, rooms: [] },
|
||||
],
|
||||
});
|
||||
viewModel = new RoomListViewModel({ client: matrixClient });
|
||||
|
||||
const dispatchSpy = jest.spyOn(dispatcher, "dispatch");
|
||||
RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate);
|
||||
|
||||
expect(dispatchSpy).toHaveBeenCalledWith({
|
||||
action: Action.RoomListSectionsCollapseStateChanged,
|
||||
collapseSections: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should apply sticky room within the correct section", async () => {
|
||||
stubClient();
|
||||
viewModel = new RoomListViewModel({ client: matrixClient });
|
||||
|
||||
Reference in New Issue
Block a user