Skip to content

Commit 54f967e

Browse files
authored
Hide room header buttons if the room hasn't been created yet. (#31092)
* Hide room header buttons if the room isn't ready * update test * update unit tests * Remove on-click actions
1 parent 24fc018 commit 54f967e

File tree

3 files changed

+141
-489
lines changed

3 files changed

+141
-489
lines changed
-2.12 KB
Loading

src/components/views/rooms/RoomHeader/RoomHeader.tsx

Lines changed: 128 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
77
*/
88

99
import React, { type JSX, useCallback, useMemo, useState } from "react";
10-
import { Body as BodyText, Button, IconButton, Menu, MenuItem, Tooltip } from "@vector-im/compound-web";
10+
import { Text, Button, IconButton, Menu, MenuItem, Tooltip } from "@vector-im/compound-web";
1111
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid";
1212
import VoiceCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/voice-call-solid";
1313
import CloseCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/close";
@@ -54,22 +54,15 @@ import { RoomSettingsTab } from "../../dialogs/RoomSettingsDialog.tsx";
5454
import { useScopedRoomContext } from "../../../../contexts/ScopedRoomContext.tsx";
5555
import { ToggleableIcon } from "./toggle/ToggleableIcon.tsx";
5656
import { CurrentRightPanelPhaseContextProvider } from "../../../../contexts/CurrentRightPanelPhaseContext.tsx";
57-
import { type LocalRoom } from "../../../../models/LocalRoom.ts";
57+
import { LocalRoom } from "../../../../models/LocalRoom.ts";
5858

59-
export default function RoomHeader({
59+
function RoomHeaderButtons({
6060
room,
6161
additionalButtons,
62-
oobData,
6362
}: {
64-
room: Room | LocalRoom;
63+
room: Room;
6564
additionalButtons?: ViewRoomOpts["buttons"];
66-
oobData?: IOOBData;
6765
}): JSX.Element {
68-
const client = useMatrixClientContext();
69-
70-
const roomName = useRoomName(room);
71-
const joinRule = useRoomState(room, (state) => state.getJoinRule());
72-
7366
const members = useRoomMembers(room, 2500);
7467
const memberCount = useRoomMemberCount(room, { throttleWait: 2500, includeInvited: true });
7568

@@ -101,12 +94,9 @@ export default function RoomHeader({
10194

10295
const dmMember = useDmMember(room);
10396
const isDirectMessage = !!dmMember;
104-
const e2eStatus = useEncryptionStatus(client, room);
10597

10698
const notificationsEnabled = useFeatureEnabled("feature_notifications");
10799

108-
const askToJoinEnabled = useFeatureEnabled("feature_ask_to_join");
109-
110100
const videoClick = useCallback(
111101
(ev: React.MouseEvent) => videoCallClick(ev, callOptions[0]),
112102
[callOptions, videoCallClick],
@@ -242,7 +232,118 @@ export default function RoomHeader({
242232
isVideoRoom ||
243233
roomContext.mainSplitContentType === MainSplitContentType.MaximisedWidget ||
244234
roomContext.mainSplitContentType === MainSplitContentType.Call;
235+
return (
236+
<>
237+
{additionalButtons?.map((props) => {
238+
const label = props.label();
239+
240+
return (
241+
<Tooltip label={label} key={props.id}>
242+
<IconButton
243+
aria-label={label}
244+
onClick={(event) => {
245+
event.stopPropagation();
246+
props.onClick();
247+
}}
248+
>
249+
{typeof props.icon === "function" ? props.icon() : props.icon}
250+
</IconButton>
251+
</Tooltip>
252+
);
253+
})}
254+
255+
{isViewingCall && <CallGuestLinkButton room={room} />}
245256

257+
{hasActiveCallSession && !isConnectedToCall && !isViewingCall ? (
258+
joinCallButton
259+
) : (
260+
<>
261+
{!isVideoRoom && videoCallButton}
262+
{!useElementCallExclusively && !isVideoRoom && voiceCallButton}
263+
</>
264+
)}
265+
266+
{showChatButton && <VideoRoomChatButton room={room} />}
267+
268+
<Tooltip label={_t("common|threads")}>
269+
<IconButton
270+
indicator={notificationLevelToIndicator(threadNotifications)}
271+
onClick={(evt) => {
272+
evt.stopPropagation();
273+
RightPanelStore.instance.showOrHidePhase(RightPanelPhases.ThreadPanel);
274+
PosthogTrackers.trackInteraction("WebRoomHeaderButtonsThreadsButton", evt);
275+
}}
276+
aria-label={_t("common|threads")}
277+
>
278+
<ToggleableIcon Icon={ThreadsIcon} phase={RightPanelPhases.ThreadPanel} />
279+
</IconButton>
280+
</Tooltip>
281+
{notificationsEnabled && (
282+
<Tooltip label={_t("notifications|enable_prompt_toast_title")}>
283+
<IconButton
284+
indicator={notificationLevelToIndicator(globalNotificationState.level)}
285+
onClick={(evt) => {
286+
evt.stopPropagation();
287+
RightPanelStore.instance.showOrHidePhase(RightPanelPhases.NotificationPanel);
288+
}}
289+
aria-label={_t("notifications|enable_prompt_toast_title")}
290+
>
291+
<ToggleableIcon Icon={NotificationsIcon} phase={RightPanelPhases.NotificationPanel} />
292+
</IconButton>
293+
</Tooltip>
294+
)}
295+
296+
<Tooltip label={_t("right_panel|room_summary_card|title")}>
297+
<IconButton
298+
onClick={(evt) => {
299+
evt.stopPropagation();
300+
RightPanelStore.instance.showOrHidePhase(RightPanelPhases.RoomSummary);
301+
}}
302+
aria-label={_t("right_panel|room_summary_card|title")}
303+
>
304+
<ToggleableIcon Icon={RoomInfoIcon} phase={RightPanelPhases.RoomSummary} />
305+
</IconButton>
306+
</Tooltip>
307+
308+
{!isDirectMessage && (
309+
<Text as="div" size="sm" weight="medium">
310+
<FacePile
311+
className="mx_RoomHeader_members"
312+
members={members.slice(0, 3)}
313+
size="20px"
314+
overflow={false}
315+
viewUserOnClick={false}
316+
tooltipLabel={_t("room|header_face_pile_tooltip")}
317+
onClick={(e: ButtonEvent) => {
318+
RightPanelStore.instance.showOrHidePhase(RightPanelPhases.MemberList);
319+
e.stopPropagation();
320+
}}
321+
aria-label={_t("common|n_members", { count: memberCount })}
322+
>
323+
{formatCount(memberCount)}
324+
</FacePile>
325+
</Text>
326+
)}
327+
</>
328+
);
329+
}
330+
331+
export default function RoomHeader({
332+
room,
333+
additionalButtons,
334+
oobData,
335+
}: {
336+
room: Room | LocalRoom;
337+
additionalButtons?: ViewRoomOpts["buttons"];
338+
oobData?: IOOBData;
339+
}): JSX.Element {
340+
const client = useMatrixClientContext();
341+
const roomName = useRoomName(room);
342+
const joinRule = useRoomState(room, (state) => state.getJoinRule());
343+
const dmMember = useDmMember(room);
344+
const isDirectMessage = !!dmMember;
345+
const e2eStatus = useEncryptionStatus(client, room);
346+
const askToJoinEnabled = useFeatureEnabled("feature_ask_to_join");
246347
const onAvatarClick = (): void => {
247348
defaultDispatcher.dispatch({
248349
action: "open_room_settings",
@@ -256,23 +357,29 @@ export default function RoomHeader({
256357
<Flex as="header" align="center" gap="var(--cpd-space-3x)" className="mx_RoomHeader light-panel">
257358
<WithPresenceIndicator room={room} size="8px">
258359
{/* We hide this from the tabIndex list as it is a pointer shortcut and superfluous for a11y */}
360+
{/* Disable on-click actions until the room is created */}
259361
<RoomAvatar
260362
room={room}
261363
size="40px"
262364
oobData={oobData}
263-
onClick={onAvatarClick}
365+
onClick={room instanceof LocalRoom ? undefined : onAvatarClick}
264366
tabIndex={-1}
265367
aria-label={_t("room|header_avatar_open_settings_label")}
266368
/>
267369
</WithPresenceIndicator>
370+
{/* Disable on-click actions until the room is created */}
268371
<button
269372
aria-label={_t("right_panel|room_summary_card|title")}
270373
tabIndex={0}
271-
onClick={() => RightPanelStore.instance.showOrHidePhase(RightPanelPhases.RoomSummary)}
374+
onClick={
375+
room instanceof LocalRoom
376+
? undefined
377+
: () => RightPanelStore.instance.showOrHidePhase(RightPanelPhases.RoomSummary)
378+
}
272379
className="mx_RoomHeader_infoWrapper"
273380
>
274381
<Box flex="1" className="mx_RoomHeader_info">
275-
<BodyText
382+
<Text
276383
as="div"
277384
size="lg"
278385
weight="semibold"
@@ -316,99 +423,12 @@ export default function RoomHeader({
316423
/>
317424
</Tooltip>
318425
)}
319-
</BodyText>
426+
</Text>
320427
</Box>
321428
</button>
322-
323-
{additionalButtons?.map((props) => {
324-
const label = props.label();
325-
326-
return (
327-
<Tooltip label={label} key={props.id}>
328-
<IconButton
329-
aria-label={label}
330-
onClick={(event) => {
331-
event.stopPropagation();
332-
props.onClick();
333-
}}
334-
>
335-
{typeof props.icon === "function" ? props.icon() : props.icon}
336-
</IconButton>
337-
</Tooltip>
338-
);
339-
})}
340-
341-
{isViewingCall && <CallGuestLinkButton room={room} />}
342-
343-
{hasActiveCallSession && !isConnectedToCall && !isViewingCall ? (
344-
joinCallButton
345-
) : (
346-
<>
347-
{!isVideoRoom && videoCallButton}
348-
{!useElementCallExclusively && !isVideoRoom && voiceCallButton}
349-
</>
350-
)}
351-
352-
{showChatButton && <VideoRoomChatButton room={room} />}
353-
354-
<Tooltip label={_t("common|threads")}>
355-
<IconButton
356-
indicator={notificationLevelToIndicator(threadNotifications)}
357-
onClick={(evt) => {
358-
evt.stopPropagation();
359-
RightPanelStore.instance.showOrHidePhase(RightPanelPhases.ThreadPanel);
360-
PosthogTrackers.trackInteraction("WebRoomHeaderButtonsThreadsButton", evt);
361-
}}
362-
aria-label={_t("common|threads")}
363-
>
364-
<ToggleableIcon Icon={ThreadsIcon} phase={RightPanelPhases.ThreadPanel} />
365-
</IconButton>
366-
</Tooltip>
367-
{notificationsEnabled && (
368-
<Tooltip label={_t("notifications|enable_prompt_toast_title")}>
369-
<IconButton
370-
indicator={notificationLevelToIndicator(globalNotificationState.level)}
371-
onClick={(evt) => {
372-
evt.stopPropagation();
373-
RightPanelStore.instance.showOrHidePhase(RightPanelPhases.NotificationPanel);
374-
}}
375-
aria-label={_t("notifications|enable_prompt_toast_title")}
376-
>
377-
<ToggleableIcon Icon={NotificationsIcon} phase={RightPanelPhases.NotificationPanel} />
378-
</IconButton>
379-
</Tooltip>
380-
)}
381-
382-
<Tooltip label={_t("right_panel|room_summary_card|title")}>
383-
<IconButton
384-
onClick={(evt) => {
385-
evt.stopPropagation();
386-
RightPanelStore.instance.showOrHidePhase(RightPanelPhases.RoomSummary);
387-
}}
388-
aria-label={_t("right_panel|room_summary_card|title")}
389-
>
390-
<ToggleableIcon Icon={RoomInfoIcon} phase={RightPanelPhases.RoomSummary} />
391-
</IconButton>
392-
</Tooltip>
393-
394-
{!isDirectMessage && (
395-
<BodyText as="div" size="sm" weight="medium">
396-
<FacePile
397-
className="mx_RoomHeader_members"
398-
members={members.slice(0, 3)}
399-
size="20px"
400-
overflow={false}
401-
viewUserOnClick={false}
402-
tooltipLabel={_t("room|header_face_pile_tooltip")}
403-
onClick={(e: ButtonEvent) => {
404-
RightPanelStore.instance.showOrHidePhase(RightPanelPhases.MemberList);
405-
e.stopPropagation();
406-
}}
407-
aria-label={_t("common|n_members", { count: memberCount })}
408-
>
409-
{formatCount(memberCount)}
410-
</FacePile>
411-
</BodyText>
429+
{/* If the room is local-only then we don't want to show any additional buttons, as it won't work */}
430+
{room instanceof LocalRoom === false && (
431+
<RoomHeaderButtons room={room} additionalButtons={additionalButtons} />
412432
)}
413433
</Flex>
414434
{askToJoinEnabled && <RoomKnocksBar room={room} />}

0 commit comments

Comments
 (0)