Room list: increase startup performance when rooms have notifications (#34358)
* Throttle section header update when listening to room notifications * Update room list section header tests
This commit is contained in:
@@ -28,6 +28,7 @@ import {
|
|||||||
import PosthogTrackers from "../../PosthogTrackers";
|
import PosthogTrackers from "../../PosthogTrackers";
|
||||||
import { CallStore, CallStoreEvent } from "../../stores/CallStore";
|
import { CallStore, CallStoreEvent } from "../../stores/CallStore";
|
||||||
import { type Call, CallEvent } from "../../models/Call";
|
import { type Call, CallEvent } from "../../models/Call";
|
||||||
|
import throttle from "lodash/throttle";
|
||||||
|
|
||||||
interface RoomListSectionHeaderViewModelProps {
|
interface RoomListSectionHeaderViewModelProps {
|
||||||
tag: string;
|
tag: string;
|
||||||
@@ -182,7 +183,17 @@ export class RoomListSectionHeaderViewModel
|
|||||||
* Computes both the unread (bold) state and a merged notification decoration that aggregates
|
* Computes both the unread (bold) state and a merged notification decoration that aggregates
|
||||||
* the rooms' notifications. The activity "dot" is intentionally excluded from the decoration.
|
* the rooms' notifications. The activity "dot" is intentionally excluded from the decoration.
|
||||||
*/
|
*/
|
||||||
private updateNotificationState = (): void => {
|
private updateNotificationState = throttle(
|
||||||
|
(): void => {
|
||||||
|
this.doUpdateNotificationState();
|
||||||
|
},
|
||||||
|
200,
|
||||||
|
// Throttled because it iterates every room in the section and fires once per tracked room
|
||||||
|
// notification update, which during sync catch-up means once per incoming timeline event
|
||||||
|
{ leading: true, trailing: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
private doUpdateNotificationState = (): void => {
|
||||||
let isUnread = false;
|
let isUnread = false;
|
||||||
let isMention = false;
|
let isMention = false;
|
||||||
let isNotification = false;
|
let isNotification = false;
|
||||||
@@ -230,6 +241,7 @@ export class RoomListSectionHeaderViewModel
|
|||||||
};
|
};
|
||||||
|
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
|
this.updateNotificationState.cancel();
|
||||||
for (const state of this.roomNotificationStates) {
|
for (const state of this.roomNotificationStates) {
|
||||||
state.off(NotificationStateEvents.Update, this.updateNotificationState);
|
state.off(NotificationStateEvents.Update, this.updateNotificationState);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,11 +250,16 @@ describe("RoomListSectionHeaderViewModel", () => {
|
|||||||
let notificationState: RoomNotificationState;
|
let notificationState: RoomNotificationState;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
jest.useFakeTimers();
|
||||||
room = mkRoom(matrixClient, "!room:server");
|
room = mkRoom(matrixClient, "!room:server");
|
||||||
notificationState = new RoomNotificationState(room, false);
|
notificationState = new RoomNotificationState(room, false);
|
||||||
jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockReturnValue(notificationState);
|
jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockReturnValue(notificationState);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
|
|
||||||
it("should set isUnread to false when no rooms have notifications", () => {
|
it("should set isUnread to false when no rooms have notifications", () => {
|
||||||
const vm = new RoomListSectionHeaderViewModel({
|
const vm = new RoomListSectionHeaderViewModel({
|
||||||
tag: "m.favourite",
|
tag: "m.favourite",
|
||||||
@@ -327,6 +332,7 @@ describe("RoomListSectionHeaderViewModel", () => {
|
|||||||
jest.spyOn(notificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true);
|
jest.spyOn(notificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true);
|
||||||
notificationState.emit(NotificationStateEvents.Update);
|
notificationState.emit(NotificationStateEvents.Update);
|
||||||
|
|
||||||
|
jest.advanceTimersByTime(200);
|
||||||
expect(vm.getSnapshot().isUnread).toBe(true);
|
expect(vm.getSnapshot().isUnread).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -549,6 +555,7 @@ describe("RoomListSectionHeaderViewModel", () => {
|
|||||||
jest.spyOn(notificationState, "isMention", "get").mockReturnValue(true);
|
jest.spyOn(notificationState, "isMention", "get").mockReturnValue(true);
|
||||||
notificationState.emit(NotificationStateEvents.Update);
|
notificationState.emit(NotificationStateEvents.Update);
|
||||||
|
|
||||||
|
jest.advanceTimersByTime(200);
|
||||||
expect(vm.getSnapshot().notification?.isMention).toBe(true);
|
expect(vm.getSnapshot().notification?.isMention).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user