element-call/src/room/InCallView.jsx

195 lines
5.6 KiB
React
Raw Normal View History

2022-01-05 23:06:51 +00:00
import React, { useCallback, useMemo } from "react";
import styles from "./InCallView.module.css";
import {
HangupButton,
MicButton,
VideoButton,
ScreenshareButton,
} from "../button";
import { Header, LeftNav, RightNav, RoomHeaderInfo } from "../Header";
import VideoGrid, {
useVideoGridLayout,
} from "matrix-react-sdk/src/components/views/voip/GroupCallView/VideoGrid";
2022-01-08 00:20:55 +00:00
import { VideoTileContainer } from "matrix-react-sdk/src/components/views/voip/GroupCallView/VideoTileContainer";
2022-01-05 23:06:51 +00:00
import SimpleVideoGrid from "matrix-react-sdk/src/components/views/voip/GroupCallView/SimpleVideoGrid";
import "matrix-react-sdk/res/css/views/voip/GroupCallView/_VideoGrid.scss";
2022-01-06 01:19:03 +00:00
import { getAvatarUrl } from "../matrix-utils";
2022-01-06 00:58:55 +00:00
import { GroupCallInspector } from "./GroupCallInspector";
2022-01-06 00:55:41 +00:00
import { OverflowMenu } from "./OverflowMenu";
2022-01-06 00:58:55 +00:00
import { GridLayoutMenu } from "./GridLayoutMenu";
2022-01-05 23:06:51 +00:00
import { Avatar } from "../Avatar";
import { UserMenuContainer } from "../UserMenuContainer";
2022-02-05 00:55:57 +00:00
import { useRageshakeRequestModal } from "../settings/rageshake";
import { RageshakeRequestModal } from "./RageshakeRequestModal";
2022-01-05 23:06:51 +00:00
const canScreenshare = "getDisplayMedia" in navigator.mediaDevices;
// There is currently a bug in Safari our our code with cloning and sending MediaStreams
// or with getUsermedia and getDisplaymedia being used within the same session.
// For now we can disable screensharing in Safari.
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
export function InCallView({
client,
groupCall,
roomName,
microphoneMuted,
localVideoMuted,
toggleLocalVideoMuted,
toggleMicrophoneMuted,
userMediaFeeds,
activeSpeaker,
onLeave,
toggleScreensharing,
isScreensharing,
screenshareFeeds,
simpleGrid,
setShowInspector,
showInspector,
roomId,
}) {
const [layout, setLayout] = useVideoGridLayout(screenshareFeeds.length > 0);
2022-01-05 23:06:51 +00:00
const items = useMemo(() => {
const participants = [];
for (const callFeed of userMediaFeeds) {
participants.push({
id: callFeed.stream.id,
2022-01-07 19:42:36 +00:00
callFeed,
2022-02-04 01:28:10 +00:00
focused:
screenshareFeeds.length === 0 && layout === "spotlight"
2022-01-05 23:06:51 +00:00
? callFeed.userId === activeSpeaker
: false,
});
}
for (const callFeed of screenshareFeeds) {
2022-02-03 00:05:15 +00:00
const userMediaItem = participants.find(
2022-01-07 19:42:36 +00:00
(item) => item.callFeed.userId === callFeed.userId
2022-01-05 23:06:51 +00:00
);
2022-01-07 19:42:36 +00:00
if (userMediaItem) {
userMediaItem.presenter = true;
2022-01-05 23:06:51 +00:00
}
2022-01-07 19:42:36 +00:00
2022-02-03 00:05:15 +00:00
participants.push({
2022-01-07 19:42:36 +00:00
id: callFeed.stream.id,
callFeed,
focused: true,
});
2022-01-05 23:06:51 +00:00
}
return participants;
}, [userMediaFeeds, activeSpeaker, screenshareFeeds, layout]);
2022-01-05 23:06:51 +00:00
const onFocusTile = useCallback(
(tiles, focusedTile) => {
if (layout === "freedom") {
return tiles.map((tile) => {
if (tile === focusedTile) {
2022-02-14 19:14:09 +00:00
return { ...tile, focused: !tile.focused };
2022-01-05 23:06:51 +00:00
}
return tile;
});
} else {
return tiles;
}
},
[layout, setLayout]
);
const renderAvatar = useCallback(
(roomMember, width, height) => {
const avatarUrl = roomMember.user?.avatarUrl;
const size = Math.round(Math.min(width, height) / 2);
return (
<Avatar
key={roomMember.userId}
style={{
width: size,
height: size,
borderRadius: size,
fontSize: Math.round(size / 2),
}}
src={avatarUrl && getAvatarUrl(client, avatarUrl, 96)}
fallback={roomMember.name.slice(0, 1).toUpperCase()}
className={styles.avatar}
/>
);
},
[client]
);
2022-02-05 00:55:57 +00:00
const {
modalState: rageshakeRequestModalState,
modalProps: rageshakeRequestModalProps,
} = useRageshakeRequestModal(groupCall.room.roomId);
2022-01-05 23:06:51 +00:00
return (
<div className={styles.inRoom}>
<Header>
<LeftNav>
<RoomHeaderInfo roomName={roomName} />
</LeftNav>
<RightNav>
<GridLayoutMenu layout={layout} setLayout={setLayout} />
<UserMenuContainer preventNavigation />
2022-01-05 23:06:51 +00:00
</RightNav>
</Header>
{items.length === 0 ? (
<div className={styles.centerMessage}>
<p>Waiting for other participants...</p>
</div>
) : simpleGrid ? (
<SimpleVideoGrid items={items} />
) : (
<VideoGrid
items={items}
layout={layout}
onFocusTile={onFocusTile}
disableAnimations={isSafari}
2022-01-08 00:20:55 +00:00
>
{({ item, ...rest }) => (
<VideoTileContainer
key={item.id}
2022-02-03 00:05:15 +00:00
item={item}
2022-01-08 00:20:55 +00:00
getAvatar={renderAvatar}
showName={items.length > 2 || item.focused}
2022-01-08 00:20:55 +00:00
{...rest}
/>
)}
</VideoGrid>
2022-01-05 23:06:51 +00:00
)}
<div className={styles.footer}>
<MicButton muted={microphoneMuted} onPress={toggleMicrophoneMuted} />
<VideoButton muted={localVideoMuted} onPress={toggleLocalVideoMuted} />
{canScreenshare && !isSafari && (
<ScreenshareButton
enabled={isScreensharing}
onPress={toggleScreensharing}
/>
)}
<OverflowMenu
2022-02-05 00:55:57 +00:00
inCall
2022-01-05 23:06:51 +00:00
roomId={roomId}
setShowInspector={setShowInspector}
showInspector={showInspector}
client={client}
2022-02-05 00:55:57 +00:00
groupCall={groupCall}
2022-01-05 23:06:51 +00:00
/>
<HangupButton onPress={onLeave} />
</div>
<GroupCallInspector
client={client}
groupCall={groupCall}
show={showInspector}
/>
2022-02-05 00:55:57 +00:00
{rageshakeRequestModalState.isOpen && (
<RageshakeRequestModal {...rageshakeRequestModalProps} />
)}
2022-01-05 23:06:51 +00:00
</div>
);
}