Add screensharing behind a feature flag
This commit is contained in:
parent
7c7f7ee5a0
commit
ceffc2380c
49 changed files with 2044 additions and 164 deletions
|
@ -21,18 +21,23 @@ import {
|
|||
CallState,
|
||||
GroupCallConnectionState,
|
||||
GroupCallVideoRequest,
|
||||
PresentedSource,
|
||||
VideoFrameSource,
|
||||
} from '../types/Calling';
|
||||
import { CallingToastManager } from './CallingToastManager';
|
||||
import { ColorType } from '../types/Colors';
|
||||
import { LocalizerType } from '../types/Util';
|
||||
import { missingCaseError } from '../util/missingCaseError';
|
||||
import { DirectCallRemoteParticipant } from './DirectCallRemoteParticipant';
|
||||
import { GroupCallRemoteParticipants } from './GroupCallRemoteParticipants';
|
||||
import { GroupCallToastManager } from './GroupCallToastManager';
|
||||
import { LocalizerType } from '../types/Util';
|
||||
import { isScreenSharingEnabled } from '../util/isScreenSharingEnabled';
|
||||
import { missingCaseError } from '../util/missingCaseError';
|
||||
import { useActivateSpeakerViewOnPresenting } from '../hooks/useActivateSpeakerViewOnPresenting';
|
||||
import { NeedsScreenRecordingPermissionsModal } from './NeedsScreenRecordingPermissionsModal';
|
||||
|
||||
export type PropsType = {
|
||||
activeCall: ActiveCallType;
|
||||
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
|
||||
getPresentingSources: () => void;
|
||||
hangUp: (_: HangUpType) => void;
|
||||
i18n: LocalizerType;
|
||||
joinedAt?: number;
|
||||
|
@ -44,14 +49,17 @@ export type PropsType = {
|
|||
profileName?: string;
|
||||
title: string;
|
||||
};
|
||||
openSystemPreferencesAction: () => unknown;
|
||||
setGroupCallVideoRequest: (_: Array<GroupCallVideoRequest>) => void;
|
||||
setLocalAudio: (_: SetLocalAudioType) => void;
|
||||
setLocalVideo: (_: SetLocalVideoType) => void;
|
||||
setLocalPreview: (_: SetLocalPreviewType) => void;
|
||||
setPresenting: (_?: PresentedSource) => void;
|
||||
setRendererCanvas: (_: SetRendererCanvasType) => void;
|
||||
stickyControls: boolean;
|
||||
toggleParticipants: () => void;
|
||||
togglePip: () => void;
|
||||
toggleScreenRecordingPermissionsDialog: () => unknown;
|
||||
toggleSettings: () => void;
|
||||
toggleSpeakerView: () => void;
|
||||
};
|
||||
|
@ -59,18 +67,22 @@ export type PropsType = {
|
|||
export const CallScreen: React.FC<PropsType> = ({
|
||||
activeCall,
|
||||
getGroupCallVideoFrameSource,
|
||||
getPresentingSources,
|
||||
hangUp,
|
||||
i18n,
|
||||
joinedAt,
|
||||
me,
|
||||
openSystemPreferencesAction,
|
||||
setGroupCallVideoRequest,
|
||||
setLocalAudio,
|
||||
setLocalVideo,
|
||||
setLocalPreview,
|
||||
setPresenting,
|
||||
setRendererCanvas,
|
||||
stickyControls,
|
||||
toggleParticipants,
|
||||
togglePip,
|
||||
toggleScreenRecordingPermissionsDialog,
|
||||
toggleSettings,
|
||||
toggleSpeakerView,
|
||||
}) => {
|
||||
|
@ -78,9 +90,19 @@ export const CallScreen: React.FC<PropsType> = ({
|
|||
conversation,
|
||||
hasLocalAudio,
|
||||
hasLocalVideo,
|
||||
isInSpeakerView,
|
||||
presentingSource,
|
||||
remoteParticipants,
|
||||
showNeedsScreenRecordingPermissionsWarning,
|
||||
showParticipantsList,
|
||||
} = activeCall;
|
||||
|
||||
useActivateSpeakerViewOnPresenting(
|
||||
remoteParticipants,
|
||||
isInSpeakerView,
|
||||
toggleSpeakerView
|
||||
);
|
||||
|
||||
const toggleAudio = useCallback(() => {
|
||||
setLocalAudio({
|
||||
enabled: !hasLocalAudio,
|
||||
|
@ -93,6 +115,14 @@ export const CallScreen: React.FC<PropsType> = ({
|
|||
});
|
||||
}, [setLocalVideo, hasLocalVideo]);
|
||||
|
||||
const togglePresenting = useCallback(() => {
|
||||
if (presentingSource) {
|
||||
setPresenting();
|
||||
} else {
|
||||
getPresentingSources();
|
||||
}
|
||||
}, [getPresentingSources, presentingSource, setPresenting]);
|
||||
|
||||
const [acceptedDuration, setAcceptedDuration] = useState<number | null>(null);
|
||||
const [showControls, setShowControls] = useState(true);
|
||||
|
||||
|
@ -151,7 +181,11 @@ export const CallScreen: React.FC<PropsType> = ({
|
|||
};
|
||||
}, [toggleAudio, toggleVideo]);
|
||||
|
||||
const hasRemoteVideo = activeCall.remoteParticipants.some(
|
||||
const currentPresenter = remoteParticipants.find(
|
||||
participant => participant.presenting
|
||||
);
|
||||
|
||||
const hasRemoteVideo = remoteParticipants.some(
|
||||
remoteParticipant => remoteParticipant.hasRemoteVideo
|
||||
);
|
||||
|
||||
|
@ -183,16 +217,22 @@ export const CallScreen: React.FC<PropsType> = ({
|
|||
case CallMode.Group:
|
||||
participantCount = activeCall.remoteParticipants.length + 1;
|
||||
headerMessage = undefined;
|
||||
headerTitle = activeCall.remoteParticipants.length
|
||||
? undefined
|
||||
: i18n('calling__in-this-call--zero');
|
||||
|
||||
if (currentPresenter) {
|
||||
headerTitle = i18n('calling__presenting--person-ongoing', [
|
||||
currentPresenter.title,
|
||||
]);
|
||||
} else if (!activeCall.remoteParticipants.length) {
|
||||
headerTitle = i18n('calling__in-this-call--zero');
|
||||
}
|
||||
|
||||
isConnected =
|
||||
activeCall.connectionState === GroupCallConnectionState.Connected;
|
||||
remoteParticipantsElement = (
|
||||
<GroupCallRemoteParticipants
|
||||
getGroupCallVideoFrameSource={getGroupCallVideoFrameSource}
|
||||
i18n={i18n}
|
||||
isInSpeakerView={activeCall.isInSpeakerView}
|
||||
isInSpeakerView={isInSpeakerView}
|
||||
remoteParticipants={activeCall.remoteParticipants}
|
||||
setGroupCallVideoRequest={setGroupCallVideoRequest}
|
||||
/>
|
||||
|
@ -206,9 +246,15 @@ export const CallScreen: React.FC<PropsType> = ({
|
|||
activeCall.callMode === CallMode.Group &&
|
||||
!activeCall.remoteParticipants.length;
|
||||
|
||||
const videoButtonType = hasLocalVideo
|
||||
? CallingButtonType.VIDEO_ON
|
||||
: CallingButtonType.VIDEO_OFF;
|
||||
let videoButtonType: CallingButtonType;
|
||||
if (presentingSource) {
|
||||
videoButtonType = CallingButtonType.VIDEO_DISABLED;
|
||||
} else if (hasLocalVideo) {
|
||||
videoButtonType = CallingButtonType.VIDEO_ON;
|
||||
} else {
|
||||
videoButtonType = CallingButtonType.VIDEO_OFF;
|
||||
}
|
||||
|
||||
const audioButtonType = hasLocalAudio
|
||||
? CallingButtonType.AUDIO_ON
|
||||
: CallingButtonType.AUDIO_OFF;
|
||||
|
@ -222,6 +268,23 @@ export const CallScreen: React.FC<PropsType> = ({
|
|||
!showControls && !isAudioOnly && isConnected,
|
||||
});
|
||||
|
||||
const isGroupCall = activeCall.callMode === CallMode.Group;
|
||||
const localPreviewVideoClass = classNames({
|
||||
'module-ongoing-call__footer__local-preview__video': true,
|
||||
'module-ongoing-call__footer__local-preview__video--presenting': Boolean(
|
||||
presentingSource
|
||||
),
|
||||
});
|
||||
|
||||
let presentingButtonType: CallingButtonType;
|
||||
if (presentingSource) {
|
||||
presentingButtonType = CallingButtonType.PRESENTING_ON;
|
||||
} else if (currentPresenter) {
|
||||
presentingButtonType = CallingButtonType.PRESENTING_DISABLED;
|
||||
} else {
|
||||
presentingButtonType = CallingButtonType.PRESENTING_OFF;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
|
@ -235,20 +298,24 @@ export const CallScreen: React.FC<PropsType> = ({
|
|||
}}
|
||||
role="group"
|
||||
>
|
||||
{activeCall.callMode === CallMode.Group ? (
|
||||
<GroupCallToastManager
|
||||
connectionState={activeCall.connectionState}
|
||||
{showNeedsScreenRecordingPermissionsWarning ? (
|
||||
<NeedsScreenRecordingPermissionsModal
|
||||
toggleScreenRecordingPermissionsDialog={
|
||||
toggleScreenRecordingPermissionsDialog
|
||||
}
|
||||
i18n={i18n}
|
||||
openSystemPreferencesAction={openSystemPreferencesAction}
|
||||
/>
|
||||
) : null}
|
||||
<CallingToastManager activeCall={activeCall} i18n={i18n} />
|
||||
<div
|
||||
className={classNames('module-ongoing-call__header', controlsFadeClass)}
|
||||
>
|
||||
<CallingHeader
|
||||
canPip
|
||||
i18n={i18n}
|
||||
isInSpeakerView={activeCall.isInSpeakerView}
|
||||
isGroupCall={activeCall.callMode === CallMode.Group}
|
||||
isInSpeakerView={isInSpeakerView}
|
||||
isGroupCall={isGroupCall}
|
||||
message={headerMessage}
|
||||
participantCount={participantCount}
|
||||
showParticipantsList={showParticipantsList}
|
||||
|
@ -263,7 +330,7 @@ export const CallScreen: React.FC<PropsType> = ({
|
|||
{hasLocalVideo && isLonelyInGroup ? (
|
||||
<div className="module-ongoing-call__local-preview-fullsize">
|
||||
<video
|
||||
className="module-ongoing-call__footer__local-preview__video"
|
||||
className={localPreviewVideoClass}
|
||||
ref={localVideoRef}
|
||||
autoPlay
|
||||
/>
|
||||
|
@ -308,6 +375,13 @@ export const CallScreen: React.FC<PropsType> = ({
|
|||
controlsFadeClass
|
||||
)}
|
||||
>
|
||||
{isScreenSharingEnabled() ? (
|
||||
<CallingButton
|
||||
buttonType={presentingButtonType}
|
||||
i18n={i18n}
|
||||
onClick={togglePresenting}
|
||||
/>
|
||||
) : null}
|
||||
<CallingButton
|
||||
buttonType={videoButtonType}
|
||||
i18n={i18n}
|
||||
|
@ -333,7 +407,7 @@ export const CallScreen: React.FC<PropsType> = ({
|
|||
>
|
||||
{hasLocalVideo && !isLonelyInGroup ? (
|
||||
<video
|
||||
className="module-ongoing-call__footer__local-preview__video"
|
||||
className={localPreviewVideoClass}
|
||||
ref={localVideoRef}
|
||||
autoPlay
|
||||
/>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue