RoomList: improve performance (#32919)

* perf: add memo to room avatar view

* perf: batch rlsV3 emit

* perf: avoid to re-render the room list if the room list state and sections are same

* perf: listen only message preview of the specific room

* perf: avoid to re-render the room list item if the notification or the content is same

* chore: replace useState and useEffect by useMemo in virtualized list

* fix: listen to room name event in RoomAvatar

* fix: room avatar re-render when room is low priority
This commit is contained in:
Florian Duros
2026-03-25 19:52:45 +00:00
committed by GitHub
parent b90a32bea4
commit 441b292353
10 changed files with 71 additions and 34 deletions
@@ -6,7 +6,16 @@
*/
import { renderHook, waitFor } from "jest-matrix-react";
import { JoinRule, type MatrixClient, type Room, RoomMember, User } from "matrix-js-sdk/src/matrix";
import {
JoinRule,
type MatrixClient,
MatrixEvent,
type Room,
RoomEvent,
RoomMember,
User,
} from "matrix-js-sdk/src/matrix";
import { act } from "react";
import {
AvatarBadgeDecoration,
@@ -78,6 +87,7 @@ describe("RoomAvatarViewModel", () => {
// 4. With presence, public room, video room and low priority, low priority takes precedence
room.tags[DefaultTagID.LowPriority] = {};
act(() => room.emit(RoomEvent.Tags, new MatrixEvent(), room));
rerender(room);
expect(vm.current.badgeDecoration).toBe(AvatarBadgeDecoration.LowPriority);
});
@@ -43,6 +43,10 @@ describe("RoomListStoreV3", () => {
}
beforeEach(() => {
jest.spyOn(global, "requestAnimationFrame").mockImplementation((cb: FrameRequestCallback) => {
cb(0);
return 0;
});
jest.spyOn(SpaceStore.instance, "isRoomInSpace").mockImplementation((space) => space === MetaSpace.Home);
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockImplementation(() => MetaSpace.Home);
jest.spyOn(SpaceStore.instance, "storeReadyPromise", "get").mockImplementation(() => Promise.resolve());
@@ -20,7 +20,6 @@ import { RoomNotificationState } from "../../../src/stores/notifications/RoomNot
import { RoomNotificationStateStore } from "../../../src/stores/notifications/RoomNotificationStateStore";
import { NotificationStateEvents } from "../../../src/stores/notifications/NotificationState";
import { type MessagePreview, MessagePreviewStore } from "../../../src/stores/message-preview";
import { UPDATE_EVENT } from "../../../src/stores/AsyncStore";
import SettingsStore from "../../../src/settings/SettingsStore";
import DMRoomMap from "../../../src/utils/DMRoomMap";
import { DefaultTagID } from "../../../src/stores/room-list-v3/skip-list/tag";
@@ -200,7 +199,7 @@ describe("RoomListItemViewModel", () => {
text: "Updated message",
} as MessagePreview);
MessagePreviewStore.instance.emit(UPDATE_EVENT);
MessagePreviewStore.instance.emit(MessagePreviewStore.getPreviewChangedEventName(room));
await flushPromises();
expect(viewModel.getSnapshot().messagePreview).toBe("Updated message");