diff --git a/playwright/e2e/left-panel/room-list-panel/room-list-filter-sort.spec.ts b/playwright/e2e/left-panel/room-list-panel/room-list-filter-sort.spec.ts index 0d725753865..d3aa060a272 100644 --- a/playwright/e2e/left-panel/room-list-panel/room-list-filter-sort.spec.ts +++ b/playwright/e2e/left-panel/room-list-panel/room-list-filter-sort.spec.ts @@ -25,10 +25,6 @@ test.describe("Room list filters and sort", () => { return page.getByRole("listbox", { name: "Room list filters" }); } - function getSecondaryFilters(page: Page): Locator { - return page.getByRole("button", { name: "Filter" }); - } - function getRoomOptionsMenu(page: Page): Locator { return page.getByRole("button", { name: "Room Options" }); } @@ -181,6 +177,33 @@ test.describe("Room list filters and sort", () => { await app.client.evaluate(async (client, id) => { await client.setRoomTag(id, "m.lowpriority", { order: 0.5 }); }, lowPrioId); + + await bot.createRoom({ + name: "invited room", + invite: [user.userId], + is_direct: true, + }); + + const mentionRoomId = await app.client.createRoom({ name: "room with mention" }); + await app.client.inviteUser(mentionRoomId, bot.credentials.userId); + await bot.joinRoom(mentionRoomId); + + const clientBot = await bot.prepareClient(); + await clientBot.evaluate( + async (client, { mentionRoomId, userId }) => { + await client.sendMessage(mentionRoomId, { + // @ts-ignore ignore usage of MsgType.text + "msgtype": "m.text", + "body": "User", + "format": "org.matrix.custom.html", + "formatted_body": `User`, + "m.mentions": { + user_ids: [userId], + }, + }); + }, + { mentionRoomId, userId: user.userId }, + ); }); test("should filter the list (with primary filters)", { tag: "@screenshot" }, async ({ page, app, user }) => { @@ -197,7 +220,7 @@ test.describe("Room list filters and sort", () => { // only one room should be visible await expect(roomList.getByRole("gridcell", { name: "unread dm" })).toBeVisible(); await expect(roomList.getByRole("gridcell", { name: "unread room" })).toBeVisible(); - expect(await roomList.locator("role=gridcell").count()).toBe(2); + expect(await roomList.locator("role=gridcell").count()).toBe(4); await expect(primaryFilters).toMatchScreenshot("unread-primary-filters.png"); await primaryFilters.getByRole("option", { name: "Favourite" }).click(); @@ -206,24 +229,23 @@ test.describe("Room list filters and sort", () => { await primaryFilters.getByRole("option", { name: "People" }).click(); await expect(roomList.getByRole("gridcell", { name: "unread dm" })).toBeVisible(); - expect(await roomList.locator("role=gridcell").count()).toBe(1); + await expect(roomList.getByRole("gridcell", { name: "invited room" })).toBeVisible(); + expect(await roomList.locator("role=gridcell").count()).toBe(2); await primaryFilters.getByRole("option", { name: "Rooms" }).click(); await expect(roomList.getByRole("gridcell", { name: "unread room" })).toBeVisible(); await expect(roomList.getByRole("gridcell", { name: "favourite room" })).toBeVisible(); await expect(roomList.getByRole("gridcell", { name: "empty room" })).toBeVisible(); - expect(await roomList.locator("role=gridcell").count()).toBe(4); - }); - - test("should filter the list (with secondary filters)", { tag: "@screenshot" }, async ({ page, app, user }) => { - const roomList = getRoomList(page); - const secondaryFilters = getSecondaryFilters(page); - await secondaryFilters.click(); + await expect(roomList.getByRole("gridcell", { name: "room with mention" })).toBeVisible(); + await expect(roomList.getByRole("gridcell", { name: "Low prio room" })).toBeVisible(); + expect(await roomList.locator("role=gridcell").count()).toBe(5); - await expect(page.getByRole("menu", { name: "Filter" })).toMatchScreenshot("filter-menu.png"); + await primaryFilters.getByRole("option", { name: "Mentions" }).click(); + await expect(roomList.getByRole("gridcell", { name: "room with mention" })).toBeVisible(); + expect(await roomList.locator("role=gridcell").count()).toBe(1); - await page.getByRole("menuitem", { name: "Low priority" }).click(); - await expect(roomList.getByRole("gridcell", { name: "Low prio room" })).toBeVisible(); + await primaryFilters.getByRole("option", { name: "Invites" }).click(); + await expect(roomList.getByRole("gridcell", { name: "invited room" })).toBeVisible(); expect(await roomList.locator("role=gridcell").count()).toBe(1); }); @@ -294,15 +316,25 @@ test.describe("Room list filters and sort", () => { }, ); - test("should render the placeholder for unread filter", { tag: "@screenshot" }, async ({ page, app, user }) => { - const primaryFilters = getPrimaryFilters(page); - await primaryFilters.getByRole("option", { name: "Unread" }).click(); + [ + { filter: "Unreads", action: "Show all chats" }, + { filter: "Mentions", action: "See all activity" }, + { filter: "Invites", action: "See all activity" }, + ].forEach(({ filter, action }) => { + test( + `should render the placeholder for ${filter} filter`, + { tag: "@screenshot" }, + async ({ page, app, user }) => { + const primaryFilters = getPrimaryFilters(page); + await primaryFilters.getByRole("option", { name: filter }).click(); - const emptyRoomList = getEmptyRoomList(page); - await expect(emptyRoomList).toMatchScreenshot("unread-empty-room-list.png"); + const emptyRoomList = getEmptyRoomList(page); + await expect(emptyRoomList).toMatchScreenshot(`${filter}-empty-room-list.png`); - await emptyRoomList.getByRole("button", { name: "show all chats" }).click(); - await expect(primaryFilters.getByRole("option", { name: "Unread" })).not.toBeChecked(); + await emptyRoomList.getByRole("button", { name: action }).click(); + await expect(primaryFilters.getByRole("option", { name: filter })).not.toBeChecked(); + }, + ); }); ["People", "Rooms", "Favourite"].forEach((filter) => { diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Favourite-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Favourite-empty-room-list-linux.png index 8cf4a3c97b3..6c71c11b1d4 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Favourite-empty-room-list-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Favourite-empty-room-list-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Invites-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Invites-empty-room-list-linux.png new file mode 100644 index 00000000000..c7396da41d9 Binary files /dev/null and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Invites-empty-room-list-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Mentions-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Mentions-empty-room-list-linux.png new file mode 100644 index 00000000000..15620d36126 Binary files /dev/null and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Mentions-empty-room-list-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/People-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/People-empty-room-list-linux.png index 3f700037cbc..7b73e0b819f 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/People-empty-room-list-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/People-empty-room-list-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Rooms-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Rooms-empty-room-list-linux.png index e01564eeb40..eb3add57336 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Rooms-empty-room-list-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Rooms-empty-room-list-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Unreads-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Unreads-empty-room-list-linux.png new file mode 100644 index 00000000000..70ed4bb782d Binary files /dev/null and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/Unreads-empty-room-list-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/default-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/default-empty-room-list-linux.png index 45d2a775ea0..6781c1d3641 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/default-empty-room-list-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/default-empty-room-list-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/room-panel-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/room-panel-empty-room-list-linux.png index 9061362a491..34924cf69f9 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/room-panel-empty-room-list-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/room-panel-empty-room-list-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-dm-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-dm-linux.png index 13577e0a1bc..2f12ee4e415 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-dm-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-dm-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-empty-room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-empty-room-list-linux.png deleted file mode 100644 index 94b09ac14f5..00000000000 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-empty-room-list-linux.png and /dev/null differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-primary-filters-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-primary-filters-linux.png index 780fdd2ed31..f0cda0b5771 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-primary-filters-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unread-primary-filters-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unselected-primary-filters-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unselected-primary-filters-linux.png index 25470b17c63..7d63f923b0f 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unselected-primary-filters-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-filter-sort.spec.ts/unselected-primary-filters-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-space-menu-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-space-menu-linux.png index 6234afc8d5c..c706e71b0fa 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-space-menu-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-header.spec.ts/room-list-header-space-menu-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-linux.png index fc680e424e7..9b130b73c41 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-smallscreen-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-smallscreen-linux.png index 94e3f007327..03efec8ca5d 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-smallscreen-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list-panel.spec.ts/room-list-panel-smallscreen-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-activity-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-activity-linux.png index bc1aa9f4f11..aa73d79988b 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-activity-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-activity-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-linux.png index 1315363e7ed..fba408c922e 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-silent-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-silent-linux.png index b400beac7c4..36b7304a010 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-silent-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-hover-silent-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-invited-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-invited-linux.png index 44d90bac341..1f2b691b4ac 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-invited-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-invited-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-mark-as-unread-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-mark-as-unread-linux.png index 86032973a3b..310912e50da 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-mark-as-unread-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-mark-as-unread-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-mention-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-mention-linux.png index b134c90d3aa..9fa531f5b15 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-mention-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-mention-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-message-preview-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-message-preview-linux.png index 8970c20cb5f..dac349eb2db 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-message-preview-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-message-preview-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-notification-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-notification-linux.png index 0c99720d01a..144604ffebf 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-notification-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-notification-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-more-options-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-more-options-linux.png index 0eb95d0c0cf..c8ae8313fac 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-more-options-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-more-options-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-notification-options-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-notification-options-linux.png index 3db9fd680d6..e10bce42738 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-notification-options-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-notification-options-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-notification-options-selection-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-notification-options-selection-linux.png index 60f62ef5727..e415eb899f7 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-notification-options-selection-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-open-notification-options-selection-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-public-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-public-linux.png index c75c1d08cc3..e951f77ef2f 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-public-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-public-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-silent-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-silent-linux.png index cf8bb5a058f..57c5cb1eb7a 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-silent-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-silent-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-video-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-video-linux.png index 3ce89cc4b56..16ea4582744 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-video-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-video-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-linux.png index a664cdf0e02..f2b625f4983 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-linux.png differ diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-scrolled-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-scrolled-linux.png index 26fdeeb3806..a1752e30d31 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-scrolled-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-scrolled-linux.png differ diff --git a/src/components/viewmodels/roomlist/RoomListViewModel.tsx b/src/components/viewmodels/roomlist/RoomListViewModel.tsx index bdc78caf154..e4e50937828 100644 --- a/src/components/viewmodels/roomlist/RoomListViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListViewModel.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import { useCallback } from "react"; import type { Room } from "matrix-js-sdk/src/matrix"; -import { type PrimaryFilter, type SecondaryFilters, useFilteredRooms } from "./useFilteredRooms"; +import { type PrimaryFilter, useFilteredRooms } from "./useFilteredRooms"; import { createRoom as createRoomFunc, hasCreateRoomRights } from "./utils"; import { useEventEmitterState } from "../../../hooks/useEventEmitter"; import { UPDATE_SELECTED_SPACE } from "../../../stores/spaces"; @@ -59,16 +59,6 @@ export interface RoomListViewState { */ activePrimaryFilter?: PrimaryFilter; - /** - * A function to activate a given secondary filter. - */ - activateSecondaryFilter: (filter: SecondaryFilters) => void; - - /** - * The currently active secondary filter. - */ - activeSecondaryFilter: SecondaryFilters; - /** * The index of the active room in the room list. */ @@ -81,14 +71,7 @@ export interface RoomListViewState { */ export function useRoomListViewModel(): RoomListViewState { const matrixClient = useMatrixClientContext(); - const { - isLoadingRooms, - primaryFilters, - activePrimaryFilter, - rooms: filteredRooms, - activateSecondaryFilter, - activeSecondaryFilter, - } = useFilteredRooms(); + const { isLoadingRooms, primaryFilters, activePrimaryFilter, rooms: filteredRooms } = useFilteredRooms(); const { activeIndex, rooms } = useStickyRoomList(filteredRooms); useRoomListNavigation(rooms); @@ -111,8 +94,6 @@ export function useRoomListViewModel(): RoomListViewState { createChatRoom, primaryFilters, activePrimaryFilter, - activateSecondaryFilter, - activeSecondaryFilter, activeIndex, }; } diff --git a/src/components/viewmodels/roomlist/useFilteredRooms.tsx b/src/components/viewmodels/roomlist/useFilteredRooms.tsx index 3140e7fc0ea..c3ed4df2ae0 100644 --- a/src/components/viewmodels/roomlist/useFilteredRooms.tsx +++ b/src/components/viewmodels/roomlist/useFilteredRooms.tsx @@ -36,8 +36,6 @@ interface FilteredRooms { primaryFilters: PrimaryFilter[]; isLoadingRooms: boolean; rooms: Room[]; - activateSecondaryFilter: (filter: SecondaryFilters) => void; - activeSecondaryFilter: SecondaryFilters; /** * The currently active primary filter. * If no primary filter is active, this will be undefined. @@ -49,51 +47,11 @@ const filterKeyToNameMap: Map = new Map([ [FilterKey.UnreadFilter, _td("room_list|filters|unread")], [FilterKey.PeopleFilter, _td("room_list|filters|people")], [FilterKey.RoomsFilter, _td("room_list|filters|rooms")], + [FilterKey.MentionsFilter, _td("room_list|filters|mentions")], + [FilterKey.InvitesFilter, _td("room_list|filters|invites")], [FilterKey.FavouriteFilter, _td("room_list|filters|favourite")], ]); -/** - * These are the secondary filters which are not prominently shown - * in the UI. - */ -export const enum SecondaryFilters { - AllActivity, - MentionsOnly, - InvitesOnly, - LowPriority, -} - -/** - * A map from {@link SecondaryFilters} which the UI understands to - * {@link FilterKey} which the store understands. - */ -const secondaryFiltersToFilterKeyMap = new Map([ - [SecondaryFilters.AllActivity, undefined], - [SecondaryFilters.MentionsOnly, FilterKey.MentionsFilter], - [SecondaryFilters.InvitesOnly, FilterKey.InvitesFilter], - [SecondaryFilters.LowPriority, FilterKey.LowPriorityFilter], -]); - -/** - * Use this function to determine if a given primary filter is compatible with - * a given secondary filter. Practically, this determines whether it makes sense - * to expose two filters together in the UI - for eg, it does not make sense to show the - * favourite primary filter if the active secondary filter is low priority. - * @param primary Primary filter key - * @param secondary Secondary filter key - * @returns true if compatible, false otherwise - */ -function isPrimaryFilterCompatible(primary: FilterKey, secondary: FilterKey): boolean { - if (secondary === FilterKey.MentionsFilter) { - if (primary === FilterKey.UnreadFilter) return false; - } else if (secondary === FilterKey.InvitesFilter) { - if (primary === FilterKey.UnreadFilter || primary === FilterKey.FavouriteFilter) return false; - } else if (secondary === FilterKey.LowPriorityFilter) { - if (primary === FilterKey.FavouriteFilter) return false; - } - return true; -} - /** * Track available filters and provide a filtered list of rooms. */ @@ -103,16 +61,6 @@ export function useFilteredRooms(): FilteredRooms { * rendered above the room list. */ const [primaryFilter, setPrimaryFilter] = useState(); - /** - * Secondary filters are also filters but they are hidden - * away in a popup menu. - */ - const [activeSecondaryFilter, setActiveSecondaryFilter] = useState(SecondaryFilters.AllActivity); - - const secondaryFilter = useMemo( - () => secondaryFiltersToFilterKeyMap.get(activeSecondaryFilter), - [activeSecondaryFilter], - ); const [rooms, setRooms] = useState(() => RoomListStoreV3.instance.getSortedRoomsInActiveSpace()); const [isLoadingRooms, setIsLoadingRooms] = useState(() => RoomListStoreV3.instance.isLoadingRooms); @@ -123,16 +71,13 @@ export function useFilteredRooms(): FilteredRooms { }, []); // Reset filters when active space changes - useEventEmitter(SpaceStore.instance, UPDATE_SELECTED_SPACE, () => { - setPrimaryFilter(undefined); - activateSecondaryFilter(SecondaryFilters.AllActivity); - }); + useEventEmitter(SpaceStore.instance, UPDATE_SELECTED_SPACE, () => setPrimaryFilter(undefined)); const filterUndefined = (array: (FilterKey | undefined)[]): FilterKey[] => array.filter((f) => f !== undefined) as FilterKey[]; const getAppliedFilters = (): FilterKey[] => { - return filterUndefined([primaryFilter, secondaryFilter]); + return filterUndefined([primaryFilter]); }; useEventEmitter(RoomListStoreV3.instance, LISTS_UPDATE_EVENT, () => { @@ -144,30 +89,6 @@ export function useFilteredRooms(): FilteredRooms { setIsLoadingRooms(false); }); - /** - * Secondary filters are activated using this function. - * This is different to how primary filters work because the secondary - * filters are static i.e they are always available and don't need to be - * hidden. - */ - const activateSecondaryFilter = useCallback( - (filter: SecondaryFilters): void => { - // If the filter is already active, just return. - if (filter === activeSecondaryFilter) return; - - // SecondaryFilter is an enum for the UI, let's convert it to something - // that the store will understand. - const secondary = secondaryFiltersToFilterKeyMap.get(filter); - setActiveSecondaryFilter(filter); - - // Reset any active primary filters. - setPrimaryFilter(undefined); - - updateRoomsFromStore(filterUndefined([secondary])); - }, - [activeSecondaryFilter, updateRoomsFromStore], - ); - /** * This tells the view which primary filters are available, how to toggle them * and whether a given primary filter is active. @see {@link PrimaryFilter} @@ -178,7 +99,7 @@ export function useFilteredRooms(): FilteredRooms { toggle: () => { setPrimaryFilter((currentFilter) => { const filter = currentFilter === key ? undefined : key; - updateRoomsFromStore(filterUndefined([filter, secondaryFilter])); + updateRoomsFromStore(filterUndefined([filter])); return filter; }); }, @@ -189,13 +110,10 @@ export function useFilteredRooms(): FilteredRooms { }; const filters: PrimaryFilter[] = []; for (const [key, name] of filterKeyToNameMap.entries()) { - if (secondaryFilter && !isPrimaryFilterCompatible(key, secondaryFilter)) { - continue; - } filters.push(createPrimaryFilter(key, _t(name))); } return filters; - }, [primaryFilter, updateRoomsFromStore, secondaryFilter]); + }, [primaryFilter, updateRoomsFromStore]); const activePrimaryFilter = useMemo(() => primaryFilters.find((filter) => filter.active), [primaryFilters]); @@ -204,7 +122,5 @@ export function useFilteredRooms(): FilteredRooms { primaryFilters, activePrimaryFilter, rooms, - activateSecondaryFilter, - activeSecondaryFilter, }; } diff --git a/src/components/views/rooms/RoomListPanel/EmptyRoomList.tsx b/src/components/views/rooms/RoomListPanel/EmptyRoomList.tsx index c4824e2b45b..1f04e4c86e1 100644 --- a/src/components/views/rooms/RoomListPanel/EmptyRoomList.tsx +++ b/src/components/views/rooms/RoomListPanel/EmptyRoomList.tsx @@ -53,7 +53,29 @@ export function EmptyRoomList({ vm }: EmptyRoomListProps): JSX.Element | undefin /> ); case FilterKey.UnreadFilter: - return ; + return ( + + ); + case FilterKey.InvitesFilter: + return ( + + ); + case FilterKey.MentionsFilter: + return ( + + ); default: return undefined; } @@ -131,18 +153,21 @@ function DefaultPlaceholder({ vm }: DefaultPlaceholderProps): JSX.Element { ); } -interface UnreadPlaceholderProps { +interface ActionPlaceholderProps { filter: PrimaryFilter; + title: string; + action: string; } /** - * The empty state for the room list when the unread filter is active + * A placeholder for the room list when a filter is active + * The user can take action to toggle the filter */ -function UnreadPlaceholder({ filter }: UnreadPlaceholderProps): JSX.Element { +function ActionPlaceholder({ filter, title, action }: ActionPlaceholderProps): JSX.Element { return ( - + - {_t("room_list|empty|show_chats")} + {action} ); diff --git a/src/components/views/rooms/RoomListPanel/RoomListFilterMenu.tsx b/src/components/views/rooms/RoomListPanel/RoomListFilterMenu.tsx deleted file mode 100644 index 532c8634ae6..00000000000 --- a/src/components/views/rooms/RoomListPanel/RoomListFilterMenu.tsx +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -import { IconButton, Menu, MenuItem, Tooltip } from "@vector-im/compound-web"; -import React, { type Ref, type JSX, useState } from "react"; -import { - ArrowDownIcon, - ChatIcon, - ChatNewIcon, - CheckIcon, - FilterIcon, - MentionIcon, -} from "@vector-im/compound-design-tokens/assets/web/icons"; - -import { _t } from "../../../../languageHandler"; -import { type RoomListViewState } from "../../../viewmodels/roomlist/RoomListViewModel"; -import { SecondaryFilters } from "../../../viewmodels/roomlist/useFilteredRooms"; -import { textForSecondaryFilter } from "./textForFilter"; - -interface MenuTriggerProps extends React.ComponentProps { - ref?: Ref; -} - -const MenuTrigger = ({ ref, ...props }: MenuTriggerProps): JSX.Element => ( - - - - - -); - -interface FilterOptionProps { - /** - * The filter to display - */ - filter: SecondaryFilters; - - /** - * True if the filter is selected - */ - selected: boolean; - - /** - * The function to call when the filter is selected - */ - onSelect: (filter: SecondaryFilters) => void; -} - -function iconForFilter(filter: SecondaryFilters, size: string): JSX.Element { - switch (filter) { - case SecondaryFilters.AllActivity: - return ; - case SecondaryFilters.MentionsOnly: - return ; - case SecondaryFilters.InvitesOnly: - return ; - case SecondaryFilters.LowPriority: - return ; - } -} - -function FilterOption({ filter, selected, onSelect }: FilterOptionProps): JSX.Element { - const checkComponent = ; - - return ( - { - onSelect(filter); - }} - > - {selected && checkComponent} - - ); -} - -interface Props { - /** - * The view model for the room list view - */ - vm: RoomListViewState; -} - -export function RoomListFilterMenu({ vm }: Props): JSX.Element { - const [open, setOpen] = useState(false); - - return ( - } - > - {[ - SecondaryFilters.AllActivity, - SecondaryFilters.MentionsOnly, - SecondaryFilters.InvitesOnly, - SecondaryFilters.LowPriority, - ].map((filter) => ( - { - vm.activateSecondaryFilter(selectedFilter); - setOpen(false); - }} - /> - ))} - - ); -} diff --git a/src/components/views/rooms/RoomListPanel/RoomListSecondaryFilters.tsx b/src/components/views/rooms/RoomListPanel/RoomListSecondaryFilters.tsx deleted file mode 100644 index 5747f9df843..00000000000 --- a/src/components/views/rooms/RoomListPanel/RoomListSecondaryFilters.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -import React, { type JSX } from "react"; - -import type { RoomListViewState } from "../../../viewmodels/roomlist/RoomListViewModel"; -import { Flex } from "../../../utils/Flex"; -import { _t } from "../../../../languageHandler"; -import { RoomListFilterMenu } from "./RoomListFilterMenu"; -import { textForSecondaryFilter } from "./textForFilter"; - -interface Props { - /** - * The view model for the room list - */ - vm: RoomListViewState; -} - -/** - * The secondary filters for the room list (eg. mentions only / invites only). - */ -export function RoomListSecondaryFilters({ vm }: Props): JSX.Element { - const activeFilterText = textForSecondaryFilter(vm.activeSecondaryFilter); - - return ( - - - {activeFilterText} - - ); -} diff --git a/src/components/views/rooms/RoomListPanel/RoomListView.tsx b/src/components/views/rooms/RoomListPanel/RoomListView.tsx index 1f91b45a364..f6d99625aa0 100644 --- a/src/components/views/rooms/RoomListPanel/RoomListView.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomListView.tsx @@ -11,7 +11,6 @@ import { useRoomListViewModel } from "../../../viewmodels/roomlist/RoomListViewM import { RoomList } from "./RoomList"; import { EmptyRoomList } from "./EmptyRoomList"; import { RoomListPrimaryFilters } from "./RoomListPrimaryFilters"; -import { RoomListSecondaryFilters } from "./RoomListSecondaryFilters"; /** * Host the room list and the (future) room filters @@ -30,7 +29,6 @@ export function RoomListView(): JSX.Element { return ( <> - {listBody} > ); diff --git a/src/components/views/rooms/RoomListPanel/textForFilter.ts b/src/components/views/rooms/RoomListPanel/textForFilter.ts deleted file mode 100644 index efb748937ad..00000000000 --- a/src/components/views/rooms/RoomListPanel/textForFilter.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -import { _t } from "../../../../languageHandler"; -import { SecondaryFilters } from "../../../viewmodels/roomlist/useFilteredRooms"; - -/** - * Gives the human readable text name for a secondary filter. - * @param filter The filter in question - * @returns The translated, human readable name for the filter - */ -export function textForSecondaryFilter(filter: SecondaryFilters): string { - switch (filter) { - case SecondaryFilters.AllActivity: - return _t("room_list|secondary_filter|all_activity"); - case SecondaryFilters.MentionsOnly: - return _t("room_list|secondary_filter|mentions_only"); - case SecondaryFilters.InvitesOnly: - return _t("room_list|secondary_filter|invites_only"); - case SecondaryFilters.LowPriority: - return _t("room_list|secondary_filter|low_priority"); - default: - throw new Error("Unknown filter"); - } -} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0be68b65e78..7d366915083 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2109,19 +2109,23 @@ "no_chats_description_no_room_rights": "Get started by messaging someone", "no_favourites": "You don't have favourite chat yet", "no_favourites_description": "You can add a chat to your favourites in the chat settings", + "no_invites": "You don't have any unread invites", + "no_mentions": "You don't have any unread mentions", "no_people": "You don’t have direct chats with anyone yet", "no_people_description": "You can deselect filters in order to see your other chats", "no_rooms": "You’re not in any room yet", "no_rooms_description": "You can deselect filters in order to see your other chats", "no_unread": "Congrats! You don’t have any unread messages", + "show_activity": "See all activity", "show_chats": "Show all chats" }, "failed_add_tag": "Failed to add tag %(tagName)s to room", "failed_remove_tag": "Failed to remove tag %(tagName)s from room", "failed_set_dm_tag": "Failed to set direct message tag", - "filter": "Filter", "filters": { "favourite": "Favourites", + "invites": "Invites", + "mentions": "Mentions", "people": "People", "rooms": "Rooms", "unread": "Unreads" @@ -2153,13 +2157,6 @@ "open_room": "Open room %(roomName)s" }, "room_options": "Room Options", - "secondary_filter": { - "all_activity": "All activity", - "invites_only": "Invites only", - "low_priority": "Low priority", - "mentions_only": "Mentions only" - }, - "secondary_filters": "Secondary filters", "show_less": "Show less", "show_message_previews": "Show message previews", "show_n_more": { diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index 47fe5f216e5..3f4337608e6 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -13,7 +13,6 @@ import RoomListStoreV3, { LISTS_UPDATE_EVENT } from "../../../../../src/stores/r import { mkStubRoom } from "../../../../test-utils"; import { useRoomListViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; import { FilterKey } from "../../../../../src/stores/room-list-v3/skip-list/filters"; -import { SecondaryFilters } from "../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; import { hasCreateRoomRights, createRoom } from "../../../../../src/components/viewmodels/roomlist/utils"; import dispatcher from "../../../../../src/dispatcher/dispatcher"; import { Action } from "../../../../../src/dispatcher/actions"; @@ -66,10 +65,10 @@ describe("RoomListViewModel", () => { it("should provide list of available filters", () => { mockAndCreateRooms(); const { result: vm } = renderHook(() => useRoomListViewModel()); - // should have 4 filters - expect(vm.current.primaryFilters).toHaveLength(4); + // should have 6 filters + expect(vm.current.primaryFilters).toHaveLength(6); // check the order - for (const [i, name] of ["Unreads", "People", "Rooms", "Favourites"].entries()) { + for (const [i, name] of ["Unreads", "People", "Rooms", "Mentions", "Invites", "Favourites"].entries()) { expect(vm.current.primaryFilters[i].name).toEqual(name); expect(vm.current.primaryFilters[i].active).toEqual(false); } @@ -107,46 +106,6 @@ describe("RoomListViewModel", () => { expect(vm.current.primaryFilters[j].active).toEqual(true); }); - it("should select all activity as default secondary filter", () => { - mockAndCreateRooms(); - const { result: vm } = renderHook(() => useRoomListViewModel()); - - // By default, all activity should be the active secondary filter - expect(vm.current.activeSecondaryFilter).toEqual(SecondaryFilters.AllActivity); - }); - - it("should be able to filter using secondary filters", () => { - const { fn } = mockAndCreateRooms(); - const { result: vm } = renderHook(() => useRoomListViewModel()); - - // Let's say we toggle the mentions secondary filter - act(() => { - vm.current.activateSecondaryFilter(SecondaryFilters.MentionsOnly); - }); - expect(fn).toHaveBeenCalledWith([FilterKey.MentionsFilter]); - }); - - it("primary filters are applied on top of secondary filers", () => { - const { fn } = mockAndCreateRooms(); - const { result: vm } = renderHook(() => useRoomListViewModel()); - - // Let's say we toggle the mentions secondary filter - act(() => { - vm.current.activateSecondaryFilter(SecondaryFilters.MentionsOnly); - }); - - // Let's say we toggle the People filter - const i = vm.current.primaryFilters.findIndex((f) => f.name === "People"); - act(() => { - vm.current.primaryFilters[i].toggle(); - }); - - // RLS call must include both these filters - expect(fn).toHaveBeenLastCalledWith( - expect.arrayContaining([FilterKey.PeopleFilter, FilterKey.MentionsFilter]), - ); - }); - it("should return the current active primary filter", async () => { // Let's say that the user's preferred sorting is alphabetic mockAndCreateRooms(); @@ -160,29 +119,6 @@ describe("RoomListViewModel", () => { expect(vm.current.activePrimaryFilter).toEqual(vm.current.primaryFilters[i]); }); - it("should remove any active primary filters when secondary filter is changed", async () => { - const { fn } = mockAndCreateRooms(); - const { result: vm } = renderHook(() => useRoomListViewModel()); - - // Let's first toggle the People filter - const i = vm.current.primaryFilters.findIndex((f) => f.name === "People"); - act(() => { - vm.current.primaryFilters[i].toggle(); - }); - expect(vm.current.primaryFilters[i].active).toEqual(true); - - // Let's say we toggle the mentions secondary filter - act(() => { - vm.current.activateSecondaryFilter(SecondaryFilters.MentionsOnly); - }); - - // Primary filer should have been unapplied - expect(vm.current.primaryFilters[i].active).toEqual(false); - - // RLS call must include only the secondary filter - expect(fn).toHaveBeenLastCalledWith(expect.arrayContaining([FilterKey.MentionsFilter])); - }); - it("should remove all filters when active space is changed", async () => { mockAndCreateRooms(); const { result: vm } = renderHook(() => useRoomListViewModel()); @@ -194,58 +130,11 @@ describe("RoomListViewModel", () => { }); expect(vm.current.primaryFilters[i].active).toEqual(true); - // Let's say we toggle the mentions secondary filter - act(() => { - vm.current.activateSecondaryFilter(SecondaryFilters.MentionsOnly); - }); - expect(vm.current.activeSecondaryFilter).toEqual(SecondaryFilters.MentionsOnly); - // Simulate a space change await act(() => SpaceStore.instance.emit(UPDATE_SELECTED_SPACE)); // Primary filer should have been unapplied expect(vm.current.activePrimaryFilter).toEqual(undefined); - - // Secondary filter should be reset to "All Activity" - expect(vm.current.activeSecondaryFilter).toEqual(SecondaryFilters.AllActivity); - }); - - const testcases: Array<[string, { secondary: SecondaryFilters; filterKey: FilterKey }, string]> = [ - [ - "Mentions only", - { secondary: SecondaryFilters.MentionsOnly, filterKey: FilterKey.MentionsFilter }, - "Unreads", - ], - [ - "Invites only", - { secondary: SecondaryFilters.InvitesOnly, filterKey: FilterKey.InvitesFilter }, - "Unreads", - ], - [ - "Invites only", - { secondary: SecondaryFilters.InvitesOnly, filterKey: FilterKey.InvitesFilter }, - "Favourites", - ], - [ - "Low priority", - { secondary: SecondaryFilters.LowPriority, filterKey: FilterKey.LowPriorityFilter }, - "Favourites", - ], - ]; - - describe.each(testcases)("For secondary filter: %s", (secondaryFilterName, secondary, primaryFilterName) => { - it(`should hide incompatible primary filter: ${primaryFilterName}`, () => { - mockAndCreateRooms(); - const { result: vm } = renderHook(() => useRoomListViewModel()); - - // Apply the secondary filter - act(() => { - vm.current.activateSecondaryFilter(secondary.secondary); - }); - - // Incompatible primary filter must be hidden - expect(vm.current.primaryFilters.find((f) => f.name === primaryFilterName)).toBeUndefined(); - }); }); }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx index 89b14c1680f..a8f87a42414 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/EmptyRoomList-test.tsx @@ -10,7 +10,6 @@ import { render, screen } from "jest-matrix-react"; import userEvent from "@testing-library/user-event"; import { type RoomListViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; -import { SecondaryFilters } from "../../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; import { EmptyRoomList } from "../../../../../../src/components/views/rooms/RoomListPanel/EmptyRoomList"; import { FilterKey } from "../../../../../../src/stores/room-list-v3/skip-list/filters"; @@ -22,8 +21,6 @@ describe("", () => { isLoadingRooms: false, rooms: [], primaryFilters: [], - activateSecondaryFilter: jest.fn().mockReturnValue({}), - activeSecondaryFilter: SecondaryFilters.AllActivity, createRoom: jest.fn(), createChatRoom: jest.fn(), canCreateRoom: true, @@ -53,13 +50,17 @@ describe("", () => { expect(asFragment()).toMatchSnapshot(); }); - it("should display the empty state for the unread filter", async () => { + it.each([ + { key: FilterKey.UnreadFilter, name: "unread", action: "Show all chats" }, + { key: FilterKey.MentionsFilter, name: "mention", action: "See all activity" }, + { key: FilterKey.InvitesFilter, name: "invite", action: "See all activity" }, + ])("should display the empty state for the $name filter", async ({ key, name, action }) => { const user = userEvent.setup(); const activePrimaryFilter = { toggle: jest.fn(), active: true, - name: "unread", - key: FilterKey.UnreadFilter, + name, + key, }; const newState = { ...vm, @@ -67,7 +68,7 @@ describe("", () => { }; const { asFragment } = render(); - await user.click(screen.getByRole("button", { name: "Show all chats" })); + await user.click(screen.getByRole("button", { name: action })); expect(activePrimaryFilter.toggle).toHaveBeenCalled(); expect(asFragment()).toMatchSnapshot(); }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx index b4f9925fdea..d5229ff6679 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx @@ -14,7 +14,6 @@ import { mkRoom, stubClient } from "../../../../../test-utils"; import { type RoomListViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; import { RoomList } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomList"; import DMRoomMap from "../../../../../../src/utils/DMRoomMap"; -import { SecondaryFilters } from "../../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; import { Landmark, LandmarkNavigation } from "../../../../../../src/accessibility/LandmarkNavigation"; describe("", () => { @@ -33,8 +32,6 @@ describe("", () => { isLoadingRooms: false, rooms, primaryFilters: [], - activateSecondaryFilter: () => {}, - activeSecondaryFilter: SecondaryFilters.AllActivity, createRoom: jest.fn(), createChatRoom: jest.fn(), canCreateRoom: true, diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListFilterMenu-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListFilterMenu-test.tsx deleted file mode 100644 index 8d549e5e266..00000000000 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListFilterMenu-test.tsx +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -import React from "react"; -import { render, type RenderOptions, screen } from "jest-matrix-react"; -import userEvent from "@testing-library/user-event"; -import { TooltipProvider } from "@vector-im/compound-web"; - -import { type RoomListViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; -import { SecondaryFilters } from "../../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; -import { RoomListFilterMenu } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListFilterMenu"; - -function getRenderOptions(): RenderOptions { - return { - wrapper: ({ children }) => {children}, - }; -} - -describe("", () => { - let vm: RoomListViewState; - - beforeEach(() => { - vm = { - isLoadingRooms: false, - rooms: [], - canCreateRoom: true, - createRoom: jest.fn(), - createChatRoom: jest.fn(), - primaryFilters: [], - activateSecondaryFilter: () => {}, - activeSecondaryFilter: SecondaryFilters.AllActivity, - activeIndex: undefined, - }; - }); - - it("should render room list filter menu button", async () => { - const { asFragment } = render(, getRenderOptions()); - expect(screen.getByRole("button", { name: "Filter" })).toBeInTheDocument(); - expect(asFragment()).toMatchSnapshot(); - }); - - it("opens the menu on click", async () => { - const userevent = userEvent.setup(); - - render(, getRenderOptions()); - await userevent.click(screen.getByRole("button", { name: "Filter" })); - expect(screen.getByRole("menu", { name: "Filter" })).toBeInTheDocument(); - }); - - it("shows 'All activity' checked if selected", async () => { - const userevent = userEvent.setup(); - - render(, getRenderOptions()); - await userevent.click(screen.getByRole("button", { name: "Filter" })); - - const shouldBeSelected = screen.getByRole("menuitem", { name: "All activity" }); - expect(shouldBeSelected).toHaveAttribute("aria-selected", "true"); - expect(shouldBeSelected).toMatchSnapshot(); - }); - - it("shows 'Invites only' checked if selected", async () => { - const userevent = userEvent.setup(); - - vm.activeSecondaryFilter = SecondaryFilters.InvitesOnly; - render(, getRenderOptions()); - await userevent.click(screen.getByRole("button", { name: "Filter" })); - - const shouldBeSelected = screen.getByRole("menuitem", { name: "Invites only" }); - expect(shouldBeSelected).toHaveAttribute("aria-selected", "true"); - expect(shouldBeSelected).toMatchSnapshot(); - }); - - it("shows 'Low priority' checked if selected", async () => { - const userevent = userEvent.setup(); - - vm.activeSecondaryFilter = SecondaryFilters.LowPriority; - render(, getRenderOptions()); - await userevent.click(screen.getByRole("button", { name: "Filter" })); - - const shouldBeSelected = screen.getByRole("menuitem", { name: "Low priority" }); - expect(shouldBeSelected).toHaveAttribute("aria-selected", "true"); - expect(shouldBeSelected).toMatchSnapshot(); - }); - - it("shows 'Mentions only' checked if selected", async () => { - const userevent = userEvent.setup(); - - vm.activeSecondaryFilter = SecondaryFilters.MentionsOnly; - render(, getRenderOptions()); - await userevent.click(screen.getByRole("button", { name: "Filter" })); - - const shouldBeSelected = screen.getByRole("menuitem", { name: "Mentions only" }); - expect(shouldBeSelected).toHaveAttribute("aria-selected", "true"); - expect(shouldBeSelected).toMatchSnapshot(); - }); - - it("activates filter when item clicked", async () => { - const userevent = userEvent.setup(); - - vm.activateSecondaryFilter = jest.fn(); - render(, getRenderOptions()); - await userevent.click(screen.getByRole("button", { name: "Filter" })); - await userevent.click(screen.getByRole("menuitem", { name: "Invites only" })); - - expect(vm.activateSecondaryFilter).toHaveBeenCalledWith(SecondaryFilters.InvitesOnly); - }); -}); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx index ec8a60a3955..fe605ce70fa 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListPrimaryFilters-test.tsx @@ -10,7 +10,6 @@ import { render, screen } from "jest-matrix-react"; import userEvent from "@testing-library/user-event"; import { type RoomListViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; -import { SecondaryFilters } from "../../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; import { RoomListPrimaryFilters } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListPrimaryFilters"; import { FilterKey } from "../../../../../../src/stores/room-list-v3/skip-list/filters"; @@ -28,8 +27,6 @@ describe("", () => { { name: "People", active: false, toggle: jest.fn(), key: FilterKey.PeopleFilter }, { name: "Rooms", active: true, toggle: jest.fn(), key: FilterKey.RoomsFilter }, ], - activateSecondaryFilter: () => {}, - activeSecondaryFilter: SecondaryFilters.AllActivity, activeIndex: undefined, }; }); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx index 78cc3f5084f..4ebe6fc4c70 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListView-test.tsx @@ -13,7 +13,6 @@ import { type RoomListViewState, useRoomListViewModel, } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel"; -import { SecondaryFilters } from "../../../../../../src/components/viewmodels/roomlist/useFilteredRooms"; import { RoomListView } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListView"; import { mkRoom, stubClient } from "../../../../../test-utils"; @@ -26,8 +25,6 @@ describe("", () => { isLoadingRooms: false, rooms: [], primaryFilters: [], - activateSecondaryFilter: jest.fn().mockReturnValue({}), - activeSecondaryFilter: SecondaryFilters.AllActivity, createRoom: jest.fn(), createChatRoom: jest.fn(), canCreateRoom: true, diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/EmptyRoomList-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/EmptyRoomList-test.tsx.snap index bf1733c2ed5..1e6fb38ab16 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/EmptyRoomList-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/EmptyRoomList-test.tsx.snap @@ -63,6 +63,56 @@ exports[` should display empty state for filter rooms 1`] = ` `; +exports[` should display the empty state for the invite filter 1`] = ` + + + + You don't have any unread invites + + + See all activity + + + +`; + +exports[` should display the empty state for the mention filter 1`] = ` + + + + You don't have any unread mentions + + + See all activity + + + +`; + exports[` should display the empty state for the unread filter 1`] = ` should render room list filter menu button 1`] = ` - - - - - - - - - -`; - -exports[` shows 'All activity' checked if selected 1`] = ` - - - - - - All activity - - - - - -`; - -exports[` shows 'Invites only' checked if selected 1`] = ` - - - - - - - Invites only - - - - - -`; - -exports[` shows 'Low priority' checked if selected 1`] = ` - - - - - - Low priority - - - - - -`; - -exports[` shows 'Mentions only' checked if selected 1`] = ` - - - - - - Mentions only - - - - - -`; diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap index c382698d492..1cfb1708294 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListPanel-test.tsx.snap @@ -32,10 +32,10 @@ exports[` should not render the RoomListSearch component when U aria-expanded="false" aria-haspopup="menu" aria-label="Room Options" - aria-labelledby="«rk»" + aria-labelledby="«rc»" class="_icon-button_m2erp_8" data-state="closed" - id="radix-«ri»" + id="radix-«ra»" role="button" style="--cpd-icon-button-size: 32px;" tabindex="0" @@ -146,48 +146,36 @@ exports[` should not render the RoomListSearch component when U role="button" tabindex="0" > - Favourites + Mentions - - - - - - - - - - All activity - + Invites + + + + + Favourites + + + @@ -407,48 +395,36 @@ exports[` should render the RoomListSearch component when UICom role="button" tabindex="0" > - Favourites + Mentions - - - - - - - - - - All activity - + Invites + + + + + Favourites + + +