diff --git a/playwright/snapshots/invite/invite-dialog.spec.ts/send-your-first-message-view-linux.png b/playwright/snapshots/invite/invite-dialog.spec.ts/send-your-first-message-view-linux.png index ec2d8d5443e..36ba4b247d8 100644 Binary files a/playwright/snapshots/invite/invite-dialog.spec.ts/send-your-first-message-view-linux.png and b/playwright/snapshots/invite/invite-dialog.spec.ts/send-your-first-message-view-linux.png differ diff --git a/src/components/views/rooms/RoomHeader/RoomHeader.tsx b/src/components/views/rooms/RoomHeader/RoomHeader.tsx index 8c162216ba9..cdc0a1b8a77 100644 --- a/src/components/views/rooms/RoomHeader/RoomHeader.tsx +++ b/src/components/views/rooms/RoomHeader/RoomHeader.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import React, { type JSX, useCallback, useMemo, useState } from "react"; -import { Body as BodyText, Button, IconButton, Menu, MenuItem, Tooltip } from "@vector-im/compound-web"; +import { Text, Button, IconButton, Menu, MenuItem, Tooltip } from "@vector-im/compound-web"; import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid"; import VoiceCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/voice-call-solid"; import CloseCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/close"; @@ -54,22 +54,15 @@ import { RoomSettingsTab } from "../../dialogs/RoomSettingsDialog.tsx"; import { useScopedRoomContext } from "../../../../contexts/ScopedRoomContext.tsx"; import { ToggleableIcon } from "./toggle/ToggleableIcon.tsx"; import { CurrentRightPanelPhaseContextProvider } from "../../../../contexts/CurrentRightPanelPhaseContext.tsx"; -import { type LocalRoom } from "../../../../models/LocalRoom.ts"; +import { LocalRoom } from "../../../../models/LocalRoom.ts"; -export default function RoomHeader({ +function RoomHeaderButtons({ room, additionalButtons, - oobData, }: { - room: Room | LocalRoom; + room: Room; additionalButtons?: ViewRoomOpts["buttons"]; - oobData?: IOOBData; }): JSX.Element { - const client = useMatrixClientContext(); - - const roomName = useRoomName(room); - const joinRule = useRoomState(room, (state) => state.getJoinRule()); - const members = useRoomMembers(room, 2500); const memberCount = useRoomMemberCount(room, { throttleWait: 2500, includeInvited: true }); @@ -101,12 +94,9 @@ export default function RoomHeader({ const dmMember = useDmMember(room); const isDirectMessage = !!dmMember; - const e2eStatus = useEncryptionStatus(client, room); const notificationsEnabled = useFeatureEnabled("feature_notifications"); - const askToJoinEnabled = useFeatureEnabled("feature_ask_to_join"); - const videoClick = useCallback( (ev: React.MouseEvent) => videoCallClick(ev, callOptions[0]), [callOptions, videoCallClick], @@ -242,7 +232,118 @@ export default function RoomHeader({ isVideoRoom || roomContext.mainSplitContentType === MainSplitContentType.MaximisedWidget || roomContext.mainSplitContentType === MainSplitContentType.Call; + return ( + <> + {additionalButtons?.map((props) => { + const label = props.label(); + + return ( + + { + event.stopPropagation(); + props.onClick(); + }} + > + {typeof props.icon === "function" ? props.icon() : props.icon} + + + ); + })} + + {isViewingCall && } + {hasActiveCallSession && !isConnectedToCall && !isViewingCall ? ( + joinCallButton + ) : ( + <> + {!isVideoRoom && videoCallButton} + {!useElementCallExclusively && !isVideoRoom && voiceCallButton} + + )} + + {showChatButton && } + + + { + evt.stopPropagation(); + RightPanelStore.instance.showOrHidePhase(RightPanelPhases.ThreadPanel); + PosthogTrackers.trackInteraction("WebRoomHeaderButtonsThreadsButton", evt); + }} + aria-label={_t("common|threads")} + > + + + + {notificationsEnabled && ( + + { + evt.stopPropagation(); + RightPanelStore.instance.showOrHidePhase(RightPanelPhases.NotificationPanel); + }} + aria-label={_t("notifications|enable_prompt_toast_title")} + > + + + + )} + + + { + evt.stopPropagation(); + RightPanelStore.instance.showOrHidePhase(RightPanelPhases.RoomSummary); + }} + aria-label={_t("right_panel|room_summary_card|title")} + > + + + + + {!isDirectMessage && ( + + { + RightPanelStore.instance.showOrHidePhase(RightPanelPhases.MemberList); + e.stopPropagation(); + }} + aria-label={_t("common|n_members", { count: memberCount })} + > + {formatCount(memberCount)} + + + )} + + ); +} + +export default function RoomHeader({ + room, + additionalButtons, + oobData, +}: { + room: Room | LocalRoom; + additionalButtons?: ViewRoomOpts["buttons"]; + oobData?: IOOBData; +}): JSX.Element { + const client = useMatrixClientContext(); + const roomName = useRoomName(room); + const joinRule = useRoomState(room, (state) => state.getJoinRule()); + const dmMember = useDmMember(room); + const isDirectMessage = !!dmMember; + const e2eStatus = useEncryptionStatus(client, room); + const askToJoinEnabled = useFeatureEnabled("feature_ask_to_join"); const onAvatarClick = (): void => { defaultDispatcher.dispatch({ action: "open_room_settings", @@ -256,23 +357,29 @@ export default function RoomHeader({ {/* We hide this from the tabIndex list as it is a pointer shortcut and superfluous for a11y */} + {/* Disable on-click actions until the room is created */} + {/* Disable on-click actions until the room is created */} - - {additionalButtons?.map((props) => { - const label = props.label(); - - return ( - - { - event.stopPropagation(); - props.onClick(); - }} - > - {typeof props.icon === "function" ? props.icon() : props.icon} - - - ); - })} - - {isViewingCall && } - - {hasActiveCallSession && !isConnectedToCall && !isViewingCall ? ( - joinCallButton - ) : ( - <> - {!isVideoRoom && videoCallButton} - {!useElementCallExclusively && !isVideoRoom && voiceCallButton} - - )} - - {showChatButton && } - - - { - evt.stopPropagation(); - RightPanelStore.instance.showOrHidePhase(RightPanelPhases.ThreadPanel); - PosthogTrackers.trackInteraction("WebRoomHeaderButtonsThreadsButton", evt); - }} - aria-label={_t("common|threads")} - > - - - - {notificationsEnabled && ( - - { - evt.stopPropagation(); - RightPanelStore.instance.showOrHidePhase(RightPanelPhases.NotificationPanel); - }} - aria-label={_t("notifications|enable_prompt_toast_title")} - > - - - - )} - - - { - evt.stopPropagation(); - RightPanelStore.instance.showOrHidePhase(RightPanelPhases.RoomSummary); - }} - aria-label={_t("right_panel|room_summary_card|title")} - > - - - - - {!isDirectMessage && ( - - { - RightPanelStore.instance.showOrHidePhase(RightPanelPhases.MemberList); - e.stopPropagation(); - }} - aria-label={_t("common|n_members", { count: memberCount })} - > - {formatCount(memberCount)} - - + {/* If the room is local-only then we don't want to show any additional buttons, as it won't work */} + {room instanceof LocalRoom === false && ( + )} {askToJoinEnabled && } diff --git a/test/unit-tests/components/structures/__snapshots__/RoomView-test.tsx.snap b/test/unit-tests/components/structures/__snapshots__/RoomView-test.tsx.snap index d8ffc523084..77a8440bb69 100644 --- a/test/unit-tests/components/structures/__snapshots__/RoomView-test.tsx.snap +++ b/test/unit-tests/components/structures/__snapshots__/RoomView-test.tsx.snap @@ -9,19 +9,18 @@ exports[`RoomView for a local room in state CREATING should match the snapshot 1 class="flex mx_RoomHeader light-panel" style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;" > - + - - -
-
-
- - u - - - u - -
- 2 -
-
- +
- - -
-
-
- - u - - - u - -
- 2 -
-
- + - - -
-
-
- - u - - - u - -
- 2 -
-
- + -
- - - -
- - -
-
-
- - u - - - u - -
- 2 -
-