Room List Store: Implement secondary filters (#29458)
* Implement the secondary filters * Use the new filters in the store * Write tests
This commit is contained in:
@@ -28,11 +28,22 @@ import { FavouriteFilter } from "./skip-list/filters/FavouriteFilter";
|
||||
import { UnreadFilter } from "./skip-list/filters/UnreadFilter";
|
||||
import { PeopleFilter } from "./skip-list/filters/PeopleFilter";
|
||||
import { RoomsFilter } from "./skip-list/filters/RoomsFilter";
|
||||
import { InvitesFilter } from "./skip-list/filters/InvitesFilter";
|
||||
import { MentionsFilter } from "./skip-list/filters/MentionsFilter";
|
||||
import { LowPriorityFilter } from "./skip-list/filters/LowPriorityFilter";
|
||||
|
||||
/**
|
||||
* These are the filters passed to the room skip list.
|
||||
*/
|
||||
const FILTERS = [new FavouriteFilter(), new UnreadFilter(), new PeopleFilter(), new RoomsFilter()];
|
||||
const FILTERS = [
|
||||
new FavouriteFilter(),
|
||||
new UnreadFilter(),
|
||||
new PeopleFilter(),
|
||||
new RoomsFilter(),
|
||||
new InvitesFilter(),
|
||||
new MentionsFilter(),
|
||||
new LowPriorityFilter(),
|
||||
];
|
||||
|
||||
/**
|
||||
* This store allows for fast retrieval of the room list in a sorted and filtered manner.
|
||||
|
||||
20
src/stores/room-list-v3/skip-list/filters/InvitesFilter.ts
Normal file
20
src/stores/room-list-v3/skip-list/filters/InvitesFilter.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
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 { type Room, KnownMembership } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import type { Filter } from ".";
|
||||
import { FilterKey } from ".";
|
||||
|
||||
export class InvitesFilter implements Filter {
|
||||
public matches(room: Room): boolean {
|
||||
return room.getMyMembership() === KnownMembership.Invite;
|
||||
}
|
||||
|
||||
public get key(): FilterKey.InvitesFilter {
|
||||
return FilterKey.InvitesFilter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
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 type { Room } from "matrix-js-sdk/src/matrix";
|
||||
import type { Filter } from ".";
|
||||
import { FilterKey } from ".";
|
||||
import { DefaultTagID } from "../../../room-list/models";
|
||||
|
||||
export class LowPriorityFilter implements Filter {
|
||||
public matches(room: Room): boolean {
|
||||
return !!room.tags[DefaultTagID.LowPriority];
|
||||
}
|
||||
|
||||
public get key(): FilterKey.LowPriorityFilter {
|
||||
return FilterKey.LowPriorityFilter;
|
||||
}
|
||||
}
|
||||
20
src/stores/room-list-v3/skip-list/filters/MentionsFilter.ts
Normal file
20
src/stores/room-list-v3/skip-list/filters/MentionsFilter.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
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 type { Room } from "matrix-js-sdk/src/matrix";
|
||||
import type { Filter } from ".";
|
||||
import { FilterKey } from ".";
|
||||
import { RoomNotificationStateStore } from "../../../notifications/RoomNotificationStateStore";
|
||||
|
||||
export class MentionsFilter implements Filter {
|
||||
public matches(room: Room): boolean {
|
||||
return RoomNotificationStateStore.instance.getRoomState(room).hasMentions;
|
||||
}
|
||||
|
||||
public get key(): FilterKey.MentionsFilter {
|
||||
return FilterKey.MentionsFilter;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,9 @@ export const enum FilterKey {
|
||||
UnreadFilter,
|
||||
PeopleFilter,
|
||||
RoomsFilter,
|
||||
LowPriorityFilter,
|
||||
MentionsFilter,
|
||||
InvitesFilter,
|
||||
}
|
||||
|
||||
export interface Filter {
|
||||
|
||||
@@ -469,6 +469,77 @@ describe("RoomListStoreV3", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("supports filtering invited rooms", async () => {
|
||||
const { client, rooms } = getClientAndRooms();
|
||||
|
||||
// Let's add 5 rooms that we are invited to
|
||||
const invitedRooms = getMockedRooms(client, 5);
|
||||
for (const room of invitedRooms) {
|
||||
room.getMyMembership = jest.fn().mockReturnValue(KnownMembership.Invite);
|
||||
}
|
||||
|
||||
rooms.push(...invitedRooms);
|
||||
|
||||
// Let's choose 5 rooms to put in space
|
||||
const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 100, 101, 102, 103, 104], client);
|
||||
setupMocks(spaceRoom, roomIds);
|
||||
const store = new RoomListStoreV3Class(dispatcher);
|
||||
await store.start();
|
||||
|
||||
const result = store.getSortedRoomsInActiveSpace([FilterKey.InvitesFilter]);
|
||||
expect(result).toHaveLength(5);
|
||||
for (const room of invitedRooms) {
|
||||
expect(result).toContain(room);
|
||||
}
|
||||
});
|
||||
|
||||
it("supports filtering by mentions", async () => {
|
||||
const { client, rooms } = getClientAndRooms();
|
||||
// Let's choose 5 rooms to put in space
|
||||
const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 13, 27, 75], client);
|
||||
|
||||
// Let's say 8, 27 have mentions
|
||||
jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockImplementation((room) => {
|
||||
const state = {
|
||||
hasMentions: [rooms[8], rooms[27]].includes(room),
|
||||
} as unknown as RoomNotificationState;
|
||||
return state;
|
||||
});
|
||||
|
||||
setupMocks(spaceRoom, roomIds);
|
||||
const store = new RoomListStoreV3Class(dispatcher);
|
||||
await store.start();
|
||||
|
||||
// Should only give us rooms at index 8 and 27
|
||||
const result = store.getSortedRoomsInActiveSpace([FilterKey.MentionsFilter]);
|
||||
expect(result).toHaveLength(2);
|
||||
for (const i of [8, 27]) {
|
||||
expect(result).toContain(rooms[i]);
|
||||
}
|
||||
});
|
||||
|
||||
it("supports filtering low priority rooms", async () => {
|
||||
const { client, rooms } = getClientAndRooms();
|
||||
// Let's choose 5 rooms to put in space
|
||||
const { spaceRoom, roomIds } = createSpace(rooms, [6, 8, 13, 27, 75], client);
|
||||
|
||||
// Let's say that 8, 27 an 75 are low priority rooms
|
||||
[8, 27, 75].forEach((i) => {
|
||||
rooms[i].tags[DefaultTagID.LowPriority] = {};
|
||||
});
|
||||
|
||||
setupMocks(spaceRoom, roomIds);
|
||||
const store = new RoomListStoreV3Class(dispatcher);
|
||||
await store.start();
|
||||
|
||||
// Sorted, filtered rooms should be 8, 27 and 75
|
||||
const result = store.getSortedRoomsInActiveSpace([FilterKey.LowPriorityFilter]);
|
||||
expect(result).toHaveLength(3);
|
||||
for (const i of [8, 27, 75]) {
|
||||
expect(result).toContain(rooms[i]);
|
||||
}
|
||||
});
|
||||
|
||||
it("supports multiple filters", async () => {
|
||||
const { client, rooms } = getClientAndRooms();
|
||||
// Let's choose 5 rooms to put in space
|
||||
|
||||
Reference in New Issue
Block a user