Merge branch 'develop' into germain-gg/fix-right-panel-member

This commit is contained in:
Germain 2023-09-01 12:36:49 +01:00
commit 1b8d00d1d4
141 changed files with 6493 additions and 5556 deletions

View file

@ -14,38 +14,41 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useCallback, useMemo } from "react";
import { Body as BodyText, IconButton } from "@vector-im/compound-web";
import React, { useEffect, useMemo, useState } from "react";
import { Body as BodyText, IconButton, Tooltip } from "@vector-im/compound-web";
import { Icon as VideoCallIcon } from "@vector-im/compound-design-tokens/icons/video-call.svg";
import { Icon as VoiceCallIcon } from "@vector-im/compound-design-tokens/icons/voice-call.svg";
import { Icon as ThreadsIcon } from "@vector-im/compound-design-tokens/icons/threads-solid.svg";
import { Icon as NotificationsIcon } from "@vector-im/compound-design-tokens/icons/notifications-solid.svg";
import { Icon as VerifiedIcon } from "@vector-im/compound-design-tokens/icons/verified.svg";
import { Icon as ErrorIcon } from "@vector-im/compound-design-tokens/icons/error.svg";
import { Icon as PublicIcon } from "@vector-im/compound-design-tokens/icons/public.svg";
import { CallType } from "matrix-js-sdk/src/webrtc/call";
import { EventType } from "matrix-js-sdk/src/matrix";
import { EventType, JoinRule, type Room } from "matrix-js-sdk/src/matrix";
import type { Room } from "matrix-js-sdk/src/matrix";
import { useRoomName } from "../../../hooks/useRoomName";
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePhases";
import { useTopic } from "../../../hooks/room/useTopic";
import { useAccountData } from "../../../hooks/useAccountData";
import { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
import { useRoomMemberCount, useRoomMembers } from "../../../hooks/useRoomMembers";
import { _t, getCurrentLanguage } from "../../../languageHandler";
import { _t } from "../../../languageHandler";
import { Flex } from "../../utils/Flex";
import { Box } from "../../utils/Box";
import { useRoomCallStatus } from "../../../hooks/room/useRoomCallStatus";
import LegacyCallHandler from "../../../LegacyCallHandler";
import defaultDispatcher from "../../../dispatcher/dispatcher";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { Action } from "../../../dispatcher/actions";
import { useRoomThreadNotifications } from "../../../hooks/room/useRoomThreadNotifications";
import { NotificationColor } from "../../../stores/notifications/NotificationColor";
import { useGlobalNotificationState } from "../../../hooks/useGlobalNotificationState";
import SdkConfig from "../../../SdkConfig";
import { useFeatureEnabled } from "../../../hooks/useSettings";
import { placeCall } from "../../../utils/room/placeCall";
import { useEncryptionStatus } from "../../../hooks/useEncryptionStatus";
import { E2EStatus } from "../../../utils/ShieldUtils";
import FacePile from "../elements/FacePile";
import { setPhase } from "../../../utils/room/setPhase";
import { useRoomState } from "../../../hooks/useRoomState";
import RoomAvatar from "../avatars/RoomAvatar";
import { formatCount } from "../../../utils/FormattingUtils";
/**
* A helper to transform a notification color to the what the Compound Icon Button
@ -66,19 +69,10 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
const roomName = useRoomName(room);
const roomTopic = useTopic(room);
const roomState = useRoomState(room);
const members = useRoomMembers(room);
const memberCount = useRoomMemberCount(room);
const directRoomsList = useAccountData<Record<string, string[]>>(client, EventType.Direct);
const isDirectMessage = useMemo(() => {
for (const [, dmRoomList] of Object.entries(directRoomsList)) {
if (dmRoomList.includes(room?.roomId ?? "")) {
return true;
}
}
return false;
}, [directRoomsList, room?.roomId]);
const members = useRoomMembers(room, 2500);
const memberCount = useRoomMemberCount(room, { throttleWait: 2500 });
const { voiceCallDisabledReason, voiceCallType, videoCallDisabledReason, videoCallType } = useRoomCallStatus(room);
@ -91,37 +85,21 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
return SdkConfig.get("element_call").use_exclusively && groupCallsEnabled;
}, [groupCallsEnabled]);
const placeCall = useCallback(
async (callType: CallType, platformCallType: typeof voiceCallType) => {
switch (platformCallType) {
case "legacy_or_jitsi":
await LegacyCallHandler.instance.placeCall(room.roomId, callType);
break;
// TODO: Remove the jitsi_or_element_call case and
// use the commented code below
case "element_call":
case "jitsi_or_element_call":
defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
room_id: room.roomId,
view_call: true,
metricsTrigger: undefined,
});
break;
// case "jitsi_or_element_call":
// TODO: Open dropdown menu to choice between
// EC and Jitsi. Waiting on Compound's dropdown
// component
// break;
}
},
[room.roomId],
);
const threadNotifications = useRoomThreadNotifications(room);
const globalNotificationState = useGlobalNotificationState();
const directRoomsList = useAccountData<Record<string, string[]>>(client, EventType.Direct);
const [isDirectMessage, setDirectMessage] = useState(false);
useEffect(() => {
for (const [, dmRoomList] of Object.entries(directRoomsList)) {
if (dmRoomList.includes(room?.roomId ?? "")) {
setDirectMessage(true);
break;
}
}
}, [room, directRoomsList]);
const e2eStatus = useEncryptionStatus(client, room);
return (
<Flex
as="header"
@ -132,7 +110,7 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
setPhase(RightPanelPhases.RoomSummary);
}}
>
<DecoratedRoomAvatar room={room} size="40px" displayBadge={false} />
<RoomAvatar room={room} size="40px" />
<Box flex="1" className="mx_RoomHeader_info">
<BodyText
as="div"
@ -142,8 +120,42 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
title={roomName}
role="heading"
aria-level={1}
className="mx_RoomHeader_heading"
>
{roomName}
{!isDirectMessage && roomState.getJoinRule() === JoinRule.Public && (
<Tooltip label={_t("Public room")}>
<PublicIcon
width="16px"
height="16px"
className="text-secondary"
aria-label={_t("Public room")}
/>
</Tooltip>
)}
{isDirectMessage && e2eStatus === E2EStatus.Verified && (
<Tooltip label={_t("common|verified")}>
<VerifiedIcon
width="16px"
height="16px"
className="mx_Verified"
aria-label={_t("common|verified")}
/>
</Tooltip>
)}
{isDirectMessage && e2eStatus === E2EStatus.Warning && (
<Tooltip label={_t("Untrusted")}>
<ErrorIcon
width="16px"
height="16px"
className="mx_Untrusted"
aria-label={_t("Untrusted")}
/>
</Tooltip>
)}
</BodyText>
{roomTopic && (
<BodyText as="div" size="sm" className="mx_RoomHeader_topic">
@ -156,8 +168,8 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
<IconButton
disabled={!!voiceCallDisabledReason}
title={!voiceCallDisabledReason ? _t("Voice call") : voiceCallDisabledReason!}
onClick={async () => {
placeCall(CallType.Voice, voiceCallType);
onClick={() => {
placeCall(room, CallType.Voice, voiceCallType);
}}
>
<VoiceCallIcon />
@ -167,7 +179,7 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
disabled={!!videoCallDisabledReason}
title={!videoCallDisabledReason ? _t("Video call") : videoCallDisabledReason!}
onClick={() => {
placeCall(CallType.Video, videoCallType);
placeCall(room, CallType.Video, videoCallType);
}}
>
<VideoCallIcon />
@ -208,7 +220,7 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
size="20px"
overflow={false}
>
{memberCount.toLocaleString(getCurrentLanguage())}
{formatCount(memberCount)}
</FacePile>
</BodyText>
)}