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
@@ -19,7 +19,6 @@ import type { RoomNotificationState } from "../../stores/notifications/RoomNotif
import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore";
import { NotificationStateEvents } from "../../stores/notifications/NotificationState";
import { MessagePreviewStore } from "../../stores/message-preview";
import { UPDATE_EVENT } from "../../stores/AsyncStore";
import { DefaultTagID } from "../../stores/room-list-v3/skip-list/tag";
import DMRoomMap from "../../utils/DMRoomMap";
import SettingsStore from "../../settings/SettingsStore";
@@ -32,6 +31,7 @@ import { UIComponent } from "../../settings/UIFeature";
import { CallStore, CallStoreEvent } from "../../stores/CallStore";
import { clearRoomNotification, setMarkedUnreadState } from "../../utils/notifications";
import { tagRoom } from "../../utils/room/tagRoom";
import { keepIfSame } from "../../utils/keepIfSame";
import dispatcher from "../../dispatcher/dispatcher";
import { Action } from "../../dispatcher/actions";
import type { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
@@ -69,8 +69,12 @@ export class RoomListItemViewModel
// Subscribe to notification state changes for this room
this.disposables.trackListener(this.notifState, NotificationStateEvents.Update, this.onNotificationChanged);
// Subscribe to message preview changes (will filter to this room)
this.disposables.trackListener(MessagePreviewStore.instance, UPDATE_EVENT, this.onMessagePreviewChanged);
// Subscribe to message preview changes for this specific room
this.disposables.trackListener(
MessagePreviewStore.instance,
MessagePreviewStore.getPreviewChangedEventName(props.room),
this.onMessagePreviewChanged,
);
// Subscribe to settings changes for message preview toggle
const settingsWatchRef = SettingsStore.watchSetting(
@@ -163,8 +167,12 @@ export class RoomListItemViewModel
*/
private updateItem(): void {
const newItem = RoomListItemViewModel.generateItemSync(this.props.room, this.props.client, this.notifState);
// Preserve message preview - it's managed separately by loadAndSetMessagePreview
this.snapshot.set({ ...newItem, messagePreview: this.snapshot.current.messagePreview });
this.snapshot.merge({
...newItem,
notification: keepIfSame(this.snapshot.current.notification, newItem.notification),
// Preserve message preview - it's managed separately by loadAndSetMessagePreview
messagePreview: this.snapshot.current.messagePreview,
});
}
private getMessagePreviewTag(): string {
@@ -452,8 +452,8 @@ export class RoomListViewModel
isLoadingRooms,
isRoomListEmpty,
activeFilterId,
roomListState,
sections,
roomListState: keepIfSame(this.snapshot.current.roomListState, roomListState),
sections: keepIfSame(this.snapshot.current.sections, sections),
});
}