signal-desktop/ts/state/smart/CallManager.tsx

153 lines
4.6 KiB
TypeScript
Raw Normal View History

2020-10-30 20:34:04 +00:00
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
2020-08-27 00:03:42 +00:00
import React from 'react';
2020-06-04 18:16:19 +00:00
import { connect } from 'react-redux';
import { mapDispatchToProps } from '../actions';
import { CallManager } from '../../components/CallManager';
2020-11-13 19:57:55 +00:00
import { calling as callingService } from '../../services/calling';
import { getMe, getConversationSelector } from '../selectors/conversations';
2020-11-17 15:07:53 +00:00
import { getActiveCall, GroupCallParticipantInfoType } from '../ducks/calling';
2020-11-13 19:57:55 +00:00
import { getIncomingCall } from '../selectors/calling';
import {
CallMode,
GroupCallPeekedParticipantType,
GroupCallRemoteParticipantType,
} from '../../types/Calling';
2020-06-04 18:16:19 +00:00
import { StateType } from '../reducer';
import { getIntl } from '../selectors/user';
2020-08-27 00:03:42 +00:00
import { SmartCallingDeviceSelection } from './CallingDeviceSelection';
function renderDeviceSelection(): JSX.Element {
return <SmartCallingDeviceSelection />;
2020-08-27 00:03:42 +00:00
}
2020-11-13 19:57:55 +00:00
const getGroupCallVideoFrameSource = callingService.getGroupCallVideoFrameSource.bind(
callingService
);
const mapStateToActiveCallProp = (state: StateType) => {
2020-10-08 01:25:33 +00:00
const { calling } = state;
const { activeCallState } = calling;
if (!activeCallState) {
return undefined;
}
const call = getActiveCall(calling);
if (!call) {
window.log.error(
'There was an active call state but no corresponding call'
);
return undefined;
}
2020-11-17 15:07:53 +00:00
const conversationSelector = getConversationSelector(state);
const conversation = conversationSelector(activeCallState.conversationId);
if (!conversation) {
window.log.error('The active call has no corresponding conversation');
return undefined;
}
// TODO: The way we deal with remote participants isn't ideal. See DESKTOP-949.
let isCallFull = false;
const groupCallPeekedParticipants: Array<GroupCallPeekedParticipantType> = [];
2020-11-17 15:07:53 +00:00
const groupCallParticipants: Array<GroupCallRemoteParticipantType> = [];
if (call.callMode === CallMode.Group) {
isCallFull = call.peekInfo.deviceCount >= call.peekInfo.maxDevices;
call.peekInfo.conversationIds.forEach((conversationId: string) => {
const peekedConversation = conversationSelector(conversationId);
if (!peekedConversation) {
window.log.error(
'Peeked participant has no corresponding conversation'
);
return;
}
groupCallPeekedParticipants.push({
avatarPath: peekedConversation.avatarPath,
color: peekedConversation.color,
firstName: peekedConversation.firstName,
isSelf: conversationId === state.user.ourConversationId,
name: peekedConversation.name,
profileName: peekedConversation.profileName,
title: peekedConversation.title,
});
});
2020-11-17 15:07:53 +00:00
call.remoteParticipants.forEach(
(remoteParticipant: GroupCallParticipantInfoType) => {
const remoteConversation = conversationSelector(
remoteParticipant.conversationId
);
if (!remoteConversation) {
window.log.error(
'Remote participant has no corresponding conversation'
);
return;
}
groupCallParticipants.push({
avatarPath: remoteConversation.avatarPath,
color: remoteConversation.color,
demuxId: remoteParticipant.demuxId,
2020-11-17 15:07:53 +00:00
firstName: remoteConversation.firstName,
hasRemoteAudio: remoteParticipant.hasRemoteAudio,
hasRemoteVideo: remoteParticipant.hasRemoteVideo,
isSelf: remoteParticipant.isSelf,
2020-11-20 19:39:50 +00:00
name: remoteConversation.name,
2020-11-17 15:07:53 +00:00
profileName: remoteConversation.profileName,
title: remoteConversation.title,
videoAspectRatio: remoteParticipant.videoAspectRatio,
2020-11-17 15:07:53 +00:00
});
}
);
}
2020-06-04 18:16:19 +00:00
return {
activeCallState,
2020-11-17 15:07:53 +00:00
call,
conversation,
isCallFull,
groupCallPeekedParticipants,
2020-11-17 15:07:53 +00:00
groupCallParticipants,
2020-06-04 18:16:19 +00:00
};
};
const mapStateToIncomingCallProp = (state: StateType) => {
const call = getIncomingCall(state.calling);
if (!call) {
return undefined;
}
const conversation = getConversationSelector(state)(call.conversationId);
if (!conversation) {
window.log.error('The incoming call has no corresponding conversation');
return undefined;
}
return {
call,
conversation,
};
};
const mapStateToProps = (state: StateType) => ({
activeCall: mapStateToActiveCallProp(state),
availableCameras: state.calling.availableCameras,
2020-11-13 19:57:55 +00:00
getGroupCallVideoFrameSource,
i18n: getIntl(state),
incomingCall: mapStateToIncomingCallProp(state),
me: getMe(state),
renderDeviceSelection,
});
2020-06-04 18:16:19 +00:00
const smart = connect(mapStateToProps, mapDispatchToProps);
export const SmartCallManager = smart(CallManager);