diff --git a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-invited-linux.png b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-invited-linux.png index aa35ea7118..4d9fd3ccd2 100644 Binary files a/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-invited-linux.png and b/playwright/snapshots/left-panel/room-list-panel/room-list.spec.ts/room-list-item-invited-linux.png differ diff --git a/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss b/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss index 41ee00fff5..ee228ec262 100644 --- a/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss +++ b/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss @@ -20,10 +20,6 @@ &:hover { background-color: var(--cpd-color-bg-action-secondary-hovered); - - .mx_RoomListItemView_content { - padding-right: var(--cpd-space-1-5x); - } } .mx_RoomListItemView_container { diff --git a/src/components/viewmodels/roomlist/RoomListItemViewModel.tsx b/src/components/viewmodels/roomlist/RoomListItemViewModel.tsx index ad6a271e57..d20c834c70 100644 --- a/src/components/viewmodels/roomlist/RoomListItemViewModel.tsx +++ b/src/components/viewmodels/roomlist/RoomListItemViewModel.tsx @@ -66,12 +66,18 @@ export function useRoomListItemViewModel(room: Room): RoomListItemViewState { const roomTags = useEventEmitterState(room, RoomEvent.Tags, () => room.tags); const isArchived = Boolean(roomTags[DefaultTagID.Archived]); - const showHoverMenu = - hasAccessToOptionsMenu(room) || hasAccessToNotificationMenu(room, matrixClient.isGuest(), isArchived); const notificationState = useMemo(() => RoomNotificationStateStore.instance.getRoomState(room), [room]); + const invited = notificationState.invited; const a11yLabel = getA11yLabel(room, notificationState); const isBold = notificationState.hasAnyNotificationOrActivity; + // We don't want to show the hover menu if + // - there is an invitation for this room + // - the user doesn't have access to both notification and more options menus + const showHoverMenu = + !invited && + (hasAccessToOptionsMenu(room) || hasAccessToNotificationMenu(room, matrixClient.isGuest(), isArchived)); + // Video room const isVideoRoom = room.isElementVideoRoom() || room.isCallRoom(); // EC video call or video room diff --git a/src/components/views/rooms/NotificationDecoration.tsx b/src/components/views/rooms/NotificationDecoration.tsx index cfb82c461c..9cc1bee738 100644 --- a/src/components/views/rooms/NotificationDecoration.tsx +++ b/src/components/views/rooms/NotificationDecoration.tsx @@ -10,6 +10,7 @@ import MentionIcon from "@vector-im/compound-design-tokens/assets/web/icons/ment import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error-solid"; import NotificationOffIcon from "@vector-im/compound-design-tokens/assets/web/icons/notifications-off-solid"; import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid"; +import EmailIcon from "@vector-im/compound-design-tokens/assets/web/icons/email-solid"; import { UnreadCounter, Unread } from "@vector-im/compound-web"; import { Flex } from "../../utils/Flex"; @@ -56,7 +57,7 @@ export function NotificationDecoration({ > {isUnsetMessage && } {hasVideoCall && } - {invited && } + {invited && } {isMention && } {(isMention || isNotification) && } {isActivityNotification && } diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListItemViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListItemViewModel-test.tsx index 867a909f2e..be309b36ed 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListItemViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListItemViewModel-test.tsx @@ -33,6 +33,10 @@ describe("RoomListItemViewModel", () => { room = mkStubRoom("roomId", "roomName", matrixClient); }); + afterEach(() => { + jest.resetAllMocks(); + }); + it("should dispatch view room action on openRoom", async () => { const { result: vm } = renderHook( () => useRoomListItemViewModel(room), @@ -68,6 +72,20 @@ describe("RoomListItemViewModel", () => { expect(vm.current.showHoverMenu).toBe(true); }); + it("should not show hover menu if user has an invitation notification", async () => { + mocked(hasAccessToOptionsMenu).mockReturnValue(true); + + const notificationState = new RoomNotificationState(room, false); + jest.spyOn(RoomNotificationStateStore.instance, "getRoomState").mockReturnValue(notificationState); + jest.spyOn(notificationState, "invited", "get").mockReturnValue(false); + + const { result: vm } = renderHook( + () => useRoomListItemViewModel(room), + withClientContextRenderOptions(room.client), + ); + expect(vm.current.showHoverMenu).toBe(true); + }); + describe("a11yLabel", () => { let notificationState: RoomNotificationState; beforeEach(() => { @@ -108,7 +126,10 @@ describe("RoomListItemViewModel", () => { }, ])("should return the $label label", ({ mock, expected }) => { mock?.(); - const { result: vm } = renderHook(() => useRoomListItemViewModel(room)); + const { result: vm } = renderHook( + () => useRoomListItemViewModel(room), + withClientContextRenderOptions(room.client), + ); expect(vm.current.a11yLabel).toBe(expected); }); }); diff --git a/test/unit-tests/components/views/rooms/__snapshots__/NotificationDecoration-test.tsx.snap b/test/unit-tests/components/views/rooms/__snapshots__/NotificationDecoration-test.tsx.snap index be81664eb8..33ee60102b 100644 --- a/test/unit-tests/components/views/rooms/__snapshots__/NotificationDecoration-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/__snapshots__/NotificationDecoration-test.tsx.snap @@ -23,11 +23,17 @@ exports[` should render the invitation decoration 1`] data-testid="notification-decoration" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1-5x); --mx-flex-wrap: nowrap;" > - - 1 - + + `;