New room list: avoid extra render for room list item (#29752)

* fix: avoid extra render in the new room list

* fix: listen to room name changes

* fix: trigger render when notification state change

* test: fix room list item tests

* chore: fix typo `RoomNotificationState.isUnsentMessage`

* refactor: move `isNotificationDecorationVisible` into `useRoomListItemViewModel`

* refactor: recalculate notification values on notification state changes

* refactor: rename `isNotificationDecorationVisible` to `showNotificationDecoration`

* test: add test for room list item view

* test: add notification tests in room list item vm

* fix: listen to notification updates in `NotificationDecoration`

* test: update notification decoration tests

* refactor: display notification decoration according to vm

* test: update room list item view tests

* fix: a11y label computation after room name change

* refactor: improve notification handling
This commit is contained in:
Florian Duros
2025-04-16 23:40:36 +02:00
committed by GitHub
parent 6767e4d6ad
commit fd455179f7
9 changed files with 290 additions and 55 deletions
@@ -28,7 +28,6 @@ describe("<RoomListItemView />", () => {
let defaultValue: RoomListItemViewState;
let matrixClient: MatrixClient;
let room: Room;
beforeEach(() => {
matrixClient = stubClient();
room = mkRoom(matrixClient, "room1");
@@ -36,15 +35,22 @@ describe("<RoomListItemView />", () => {
DMRoomMap.makeShared(matrixClient);
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null);
const notificationState = new RoomNotificationState(room, false);
jest.spyOn(notificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true);
jest.spyOn(notificationState, "isNotification", "get").mockReturnValue(true);
jest.spyOn(notificationState, "count", "get").mockReturnValue(1);
defaultValue = {
openRoom: jest.fn(),
showHoverMenu: false,
notificationState: new RoomNotificationState(room, false),
notificationState,
a11yLabel: "Open room room1",
isBold: false,
isVideoRoom: false,
callConnectionState: null,
hasParticipantInCall: false,
name: room.name,
showNotificationDecoration: false,
};
mocked(useRoomListItemViewModel).mockReturnValue(defaultValue);
@@ -84,4 +90,30 @@ describe("<RoomListItemView />", () => {
);
expect(asFragment()).toMatchSnapshot();
});
test("should display notification decoration", async () => {
mocked(useRoomListItemViewModel).mockReturnValue({
...defaultValue,
showNotificationDecoration: true,
});
const { asFragment } = render(<RoomListItemView room={room} isSelected={false} />);
expect(screen.getByTestId("notification-decoration")).toBeInTheDocument();
expect(asFragment()).toMatchSnapshot();
});
test("should not display notification decoration when hovered", async () => {
const user = userEvent.setup();
mocked(useRoomListItemViewModel).mockReturnValue({
...defaultValue,
showNotificationDecoration: true,
});
render(<RoomListItemView room={room} isSelected={false} />);
const listItem = screen.getByRole("button", { name: `Open room ${room.name}` });
await user.hover(listItem);
expect(screen.queryByRole("notification-decoration")).toBeNull();
});
});