Centralize logic for finding/fetching the ringing call
This commit is contained in:
parent
6888bb9cba
commit
1ce3988579
6 changed files with 131 additions and 173 deletions
|
@ -105,7 +105,7 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
|||
hangUpActiveCall: action('hang-up-active-call'),
|
||||
hasInitialLoadCompleted: true,
|
||||
i18n,
|
||||
incomingCall: null,
|
||||
ringingCall: null,
|
||||
callLink: storyProps.callLink ?? undefined,
|
||||
me: {
|
||||
...getDefaultConversation({
|
||||
|
@ -148,7 +148,6 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
|||
'toggle-screen-recording-permissions-dialog'
|
||||
),
|
||||
toggleSettings: action('toggle-settings'),
|
||||
isConversationTooBigToRing: false,
|
||||
pauseVoiceNotePlayer: action('pause-audio-player'),
|
||||
});
|
||||
|
||||
|
@ -243,7 +242,7 @@ export function RingingDirectCall(): JSX.Element {
|
|||
return (
|
||||
<CallManager
|
||||
{...createProps({
|
||||
incomingCall: {
|
||||
ringingCall: {
|
||||
callMode: CallMode.Direct as const,
|
||||
conversation: getConversation(),
|
||||
isVideoCall: true,
|
||||
|
@ -257,7 +256,7 @@ export function RingingGroupCall(): JSX.Element {
|
|||
return (
|
||||
<CallManager
|
||||
{...createProps({
|
||||
incomingCall: {
|
||||
ringingCall: {
|
||||
callMode: CallMode.Group as const,
|
||||
connectionState: GroupCallConnectionState.NotConnected,
|
||||
joinState: GroupCallJoinState.NotJoined,
|
||||
|
|
|
@ -13,14 +13,13 @@ import { CallingPip } from './CallingPip';
|
|||
import { IncomingCallBar } from './IncomingCallBar';
|
||||
import type {
|
||||
ActiveCallType,
|
||||
CallingConversationType,
|
||||
CallViewMode,
|
||||
GroupCallConnectionState,
|
||||
GroupCallVideoRequest,
|
||||
} from '../types/Calling';
|
||||
import {
|
||||
CallEndedReason,
|
||||
CallState,
|
||||
GroupCallConnectionState,
|
||||
GroupCallJoinState,
|
||||
} from '../types/Calling';
|
||||
import { CallMode } from '../types/CallDisposition';
|
||||
|
@ -90,7 +89,7 @@ export type PropsType = {
|
|||
) => VideoFrameSource;
|
||||
getIsSharingPhoneNumberWithEverybody: () => boolean;
|
||||
getPresentingSources: () => void;
|
||||
incomingCall: DirectIncomingCall | GroupIncomingCall | null;
|
||||
ringingCall: DirectIncomingCall | GroupIncomingCall | null;
|
||||
renderDeviceSelection: () => JSX.Element;
|
||||
renderReactionPicker: (
|
||||
props: React.ComponentProps<typeof SmartReactionPicker>
|
||||
|
@ -140,7 +139,6 @@ export type PropsType = {
|
|||
toggleCallLinkPendingParticipantModal: (contactId: string) => void;
|
||||
toggleScreenRecordingPermissionsDialog: () => unknown;
|
||||
toggleSettings: () => void;
|
||||
isConversationTooBigToRing: boolean;
|
||||
pauseVoiceNotePlayer: () => void;
|
||||
} & Pick<ReactionPickerProps, 'renderEmojiPicker'>;
|
||||
|
||||
|
@ -153,9 +151,9 @@ type ActiveCallManagerPropsType = {
|
|||
| 'bounceAppIconStop'
|
||||
| 'declineCall'
|
||||
| 'hasInitialLoadCompleted'
|
||||
| 'incomingCall'
|
||||
| 'notifyForCall'
|
||||
| 'playRingtone'
|
||||
| 'ringingCall'
|
||||
| 'setIsCallActive'
|
||||
| 'stopRingtone'
|
||||
| 'isConversationTooBigToRing'
|
||||
|
@ -544,8 +542,6 @@ export function CallManager({
|
|||
hangUpActiveCall,
|
||||
hasInitialLoadCompleted,
|
||||
i18n,
|
||||
incomingCall,
|
||||
isConversationTooBigToRing,
|
||||
getIsSharingPhoneNumberWithEverybody,
|
||||
me,
|
||||
notifyForCall,
|
||||
|
@ -556,6 +552,7 @@ export function CallManager({
|
|||
renderDeviceSelection,
|
||||
renderEmojiPicker,
|
||||
renderReactionPicker,
|
||||
ringingCall,
|
||||
selectPresentingSource,
|
||||
sendGroupCallRaiseHand,
|
||||
sendGroupCallReaction,
|
||||
|
@ -583,16 +580,13 @@ export function CallManager({
|
|||
setIsCallActive(isCallActive);
|
||||
}, [isCallActive, setIsCallActive]);
|
||||
|
||||
const shouldRing = getShouldRing({
|
||||
activeCall,
|
||||
incomingCall,
|
||||
isConversationTooBigToRing,
|
||||
hasInitialLoadCompleted,
|
||||
});
|
||||
// It's important not to use the ringingCall itself, because that changes
|
||||
const ringingCallId = ringingCall?.conversation.id;
|
||||
useEffect(() => {
|
||||
if (shouldRing) {
|
||||
if (hasInitialLoadCompleted && ringingCallId) {
|
||||
log.info('CallManager: Playing ringtone');
|
||||
playRingtone();
|
||||
|
||||
return () => {
|
||||
log.info('CallManager: Stopping ringtone');
|
||||
stopRingtone();
|
||||
|
@ -601,7 +595,7 @@ export function CallManager({
|
|||
|
||||
stopRingtone();
|
||||
return noop;
|
||||
}, [shouldRing, playRingtone, stopRingtone]);
|
||||
}, [hasInitialLoadCompleted, playRingtone, ringingCallId, stopRingtone]);
|
||||
|
||||
const mightBeRingingOutgoingGroupCall =
|
||||
isGroupOrAdhocActiveCall(activeCall) &&
|
||||
|
@ -680,7 +674,7 @@ export function CallManager({
|
|||
}
|
||||
|
||||
// In the future, we may want to show the incoming call bar when a call is active.
|
||||
if (incomingCall) {
|
||||
if (ringingCall) {
|
||||
return (
|
||||
<IncomingCallBar
|
||||
acceptCall={acceptCall}
|
||||
|
@ -689,107 +683,10 @@ export function CallManager({
|
|||
declineCall={declineCall}
|
||||
i18n={i18n}
|
||||
notifyForCall={notifyForCall}
|
||||
{...incomingCall}
|
||||
{...ringingCall}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function isRinging(callState: CallState | undefined): boolean {
|
||||
return callState === CallState.Prering || callState === CallState.Ringing;
|
||||
}
|
||||
|
||||
function isConnected(connectionState: GroupCallConnectionState): boolean {
|
||||
return (
|
||||
connectionState === GroupCallConnectionState.Connecting ||
|
||||
connectionState === GroupCallConnectionState.Connected
|
||||
);
|
||||
}
|
||||
|
||||
function isJoined(joinState: GroupCallJoinState): boolean {
|
||||
return joinState !== GroupCallJoinState.NotJoined;
|
||||
}
|
||||
|
||||
function hasRemoteParticipants(
|
||||
remoteParticipants: Array<GroupCallParticipantInfoType>
|
||||
): boolean {
|
||||
return remoteParticipants.length > 0;
|
||||
}
|
||||
|
||||
function isLonelyGroup(conversation: CallingConversationType): boolean {
|
||||
return (conversation.sortedGroupMembers?.length ?? 0) < 2;
|
||||
}
|
||||
|
||||
function getShouldRing({
|
||||
activeCall,
|
||||
incomingCall,
|
||||
isConversationTooBigToRing,
|
||||
hasInitialLoadCompleted,
|
||||
}: Readonly<
|
||||
Pick<
|
||||
PropsType,
|
||||
| 'activeCall'
|
||||
| 'incomingCall'
|
||||
| 'isConversationTooBigToRing'
|
||||
| 'hasInitialLoadCompleted'
|
||||
>
|
||||
>): boolean {
|
||||
if (!hasInitialLoadCompleted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (incomingCall != null) {
|
||||
// don't ring a large group
|
||||
if (isConversationTooBigToRing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (activeCall != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (incomingCall.callMode === CallMode.Direct) {
|
||||
return (
|
||||
isRinging(incomingCall.callState) &&
|
||||
incomingCall.callEndedReason == null
|
||||
);
|
||||
}
|
||||
|
||||
if (incomingCall.callMode === CallMode.Group) {
|
||||
return (
|
||||
!isConnected(incomingCall.connectionState) &&
|
||||
!isJoined(incomingCall.joinState) &&
|
||||
!isLonelyGroup(incomingCall.conversation)
|
||||
);
|
||||
}
|
||||
|
||||
// Adhoc calls can't be incoming.
|
||||
|
||||
throw missingCaseError(incomingCall);
|
||||
}
|
||||
|
||||
if (activeCall != null) {
|
||||
switch (activeCall.callMode) {
|
||||
case CallMode.Direct:
|
||||
return (
|
||||
activeCall.callState === CallState.Prering ||
|
||||
activeCall.callState === CallState.Ringing
|
||||
);
|
||||
case CallMode.Group:
|
||||
case CallMode.Adhoc:
|
||||
return (
|
||||
activeCall.outgoingRing &&
|
||||
isConnected(activeCall.connectionState) &&
|
||||
isJoined(activeCall.joinState) &&
|
||||
!hasRemoteParticipants(activeCall.remoteParticipants) &&
|
||||
!isLonelyGroup(activeCall.conversation)
|
||||
);
|
||||
default:
|
||||
throw missingCaseError(activeCall);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -3,15 +3,22 @@
|
|||
|
||||
// Note that this file should not important any binary addons or Node.js modules
|
||||
// because it can be imported by storybook
|
||||
import { CallState, GroupCallConnectionState } from '../../types/Calling';
|
||||
import {
|
||||
CallState,
|
||||
GroupCallConnectionState,
|
||||
GroupCallJoinState,
|
||||
} from '../../types/Calling';
|
||||
import { CallMode } from '../../types/CallDisposition';
|
||||
|
||||
import type { CallingConversationType } from '../../types/Calling';
|
||||
import type { AciString } from '../../types/ServiceId';
|
||||
import { missingCaseError } from '../../util/missingCaseError';
|
||||
import type {
|
||||
DirectCallStateType,
|
||||
CallsByConversationType,
|
||||
GroupCallPeekInfoType,
|
||||
GroupCallStateType,
|
||||
GroupCallParticipantInfoType,
|
||||
ActiveCallStateType,
|
||||
} from './calling';
|
||||
|
||||
export const MAX_CALL_PARTICIPANTS_FOR_DEFAULT_MUTE = 8;
|
||||
|
@ -19,28 +26,53 @@ export const MAX_CALL_PARTICIPANTS_FOR_DEFAULT_MUTE = 8;
|
|||
// In theory, there could be multiple incoming calls, or an incoming call while there's
|
||||
// an active call. In practice, the UI is not ready for this, and RingRTC doesn't
|
||||
// support it for direct calls.
|
||||
export const getIncomingCall = (
|
||||
// Adhoc calls can not be incoming, so we don't look for them here.
|
||||
export const getRingingCall = (
|
||||
callsByConversation: Readonly<CallsByConversationType>,
|
||||
activeCallState: ActiveCallStateType | undefined,
|
||||
ourAci: AciString
|
||||
): undefined | DirectCallStateType | GroupCallStateType =>
|
||||
Object.values(callsByConversation).find(call => {
|
||||
switch (call.callMode) {
|
||||
case CallMode.Direct:
|
||||
return call.isIncoming && call.callState === CallState.Ringing;
|
||||
case CallMode.Group:
|
||||
return (
|
||||
call.ringerAci &&
|
||||
call.connectionState === GroupCallConnectionState.NotConnected &&
|
||||
isAnybodyElseInGroupCall(call.peekInfo, ourAci)
|
||||
);
|
||||
case CallMode.Adhoc:
|
||||
// Adhoc calls cannot be incoming.
|
||||
return;
|
||||
default:
|
||||
throw missingCaseError(call);
|
||||
): DirectCallStateType | GroupCallStateType | undefined => {
|
||||
const callList = Object.values(callsByConversation);
|
||||
const ringingDirect = callList.find(call => {
|
||||
if (call.callMode !== CallMode.Direct) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isRinging(call.callState) && call.callEndedReason == null;
|
||||
});
|
||||
|
||||
if (ringingDirect) {
|
||||
return ringingDirect;
|
||||
}
|
||||
|
||||
return callList.find(call => {
|
||||
if (call.callMode !== CallMode.Group) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Outgoing - ringerAci is not set for outgoing group calls
|
||||
if (
|
||||
activeCallState?.state === 'Active' &&
|
||||
activeCallState.outgoingRing &&
|
||||
activeCallState.conversationId === call.conversationId &&
|
||||
isConnected(call.connectionState) &&
|
||||
isJoined(call.joinState) &&
|
||||
!hasRemoteParticipants(call.remoteParticipants)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Incoming
|
||||
return (
|
||||
call.ringerAci &&
|
||||
call.ringerAci !== ourAci &&
|
||||
!isConnected(call.connectionState) &&
|
||||
!isJoined(call.joinState) &&
|
||||
isAnybodyElseInGroupCall(call.peekInfo, ourAci)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export const isAnybodyElseInGroupCall = (
|
||||
peekInfo: undefined | Readonly<Pick<GroupCallPeekInfoType, 'acis'>>,
|
||||
ourAci: AciString
|
||||
|
@ -60,3 +92,28 @@ export const isGroupCallActiveOnServer = (
|
|||
): boolean => {
|
||||
return Boolean(peekInfo?.eraId);
|
||||
};
|
||||
|
||||
export function isLonelyGroup(conversation: CallingConversationType): boolean {
|
||||
return (conversation.sortedGroupMembers?.length ?? 0) < 2;
|
||||
}
|
||||
|
||||
function isRinging(callState: CallState | undefined): boolean {
|
||||
return callState === CallState.Prering || callState === CallState.Ringing;
|
||||
}
|
||||
|
||||
function isConnected(connectionState: GroupCallConnectionState): boolean {
|
||||
return (
|
||||
connectionState === GroupCallConnectionState.Connecting ||
|
||||
connectionState === GroupCallConnectionState.Connected
|
||||
);
|
||||
}
|
||||
|
||||
function isJoined(joinState: GroupCallJoinState): boolean {
|
||||
return joinState !== GroupCallJoinState.NotJoined;
|
||||
}
|
||||
|
||||
function hasRemoteParticipants(
|
||||
remoteParticipants: Array<GroupCallParticipantInfoType>
|
||||
): boolean {
|
||||
return remoteParticipants.length > 0;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import type {
|
|||
GroupCallStateType,
|
||||
ActiveCallStateType,
|
||||
} from '../ducks/calling';
|
||||
import { getIncomingCall as getIncomingCallHelper } from '../ducks/callingHelpers';
|
||||
import { getRingingCall as getRingingCallHelper } from '../ducks/callingHelpers';
|
||||
import type { PresentedSource } from '../../types/Calling';
|
||||
import { CallMode } from '../../types/CallDisposition';
|
||||
import { isCallLinkAdmin, type CallLinkType } from '../../types/CallLink';
|
||||
|
@ -152,25 +152,27 @@ export const isInFullScreenCall = createSelector(
|
|||
Boolean(activeCallState && !activeCallState.pip)
|
||||
);
|
||||
|
||||
export const getIncomingCall = createSelector(
|
||||
export const getRingingCall = createSelector(
|
||||
getCallsByConversation,
|
||||
getActiveCallState,
|
||||
getUserACI,
|
||||
(
|
||||
callsByConversation: CallsByConversationType,
|
||||
activeCallState: ActiveCallStateType | undefined,
|
||||
ourAci: AciString | undefined
|
||||
): undefined | DirectCallStateType | GroupCallStateType => {
|
||||
if (!ourAci) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return getIncomingCallHelper(callsByConversation, ourAci);
|
||||
return getRingingCallHelper(callsByConversation, activeCallState, ourAci);
|
||||
}
|
||||
);
|
||||
|
||||
export const areAnyCallsActiveOrRinging = createSelector(
|
||||
getActiveCall,
|
||||
getIncomingCall,
|
||||
(activeCall, incomingCall): boolean => Boolean(activeCall || incomingCall)
|
||||
getRingingCall,
|
||||
(activeCall, ringingCall): boolean => Boolean(activeCall || ringingCall)
|
||||
);
|
||||
|
||||
export const getPresentingSource = createSelector(
|
||||
|
|
|
@ -48,15 +48,16 @@ import {
|
|||
getActiveCallState,
|
||||
getAvailableCameras,
|
||||
getCallLinkSelector,
|
||||
getIncomingCall,
|
||||
getRingingCall,
|
||||
} from '../selectors/calling';
|
||||
import { getConversationSelector, getMe } from '../selectors/conversations';
|
||||
import { getIntl } from '../selectors/user';
|
||||
import { getIntl, getUserACI } from '../selectors/user';
|
||||
import { SmartCallingDeviceSelection } from './CallingDeviceSelection';
|
||||
import { renderEmojiPicker } from './renderEmojiPicker';
|
||||
import { renderReactionPicker } from './renderReactionPicker';
|
||||
import { isSharingPhoneNumberWithEverybody as getIsSharingPhoneNumberWithEverybody } from '../../util/phoneNumberSharingMode';
|
||||
import { useGlobalModalActions } from '../ducks/globalModals';
|
||||
import { isLonelyGroup } from '../ducks/callingHelpers';
|
||||
|
||||
function renderDeviceSelection(): JSX.Element {
|
||||
return <SmartCallingDeviceSelection />;
|
||||
|
@ -364,56 +365,62 @@ const mapStateToCallLinkProp = (state: StateType): CallLinkType | undefined => {
|
|||
return callLink;
|
||||
};
|
||||
|
||||
const mapStateToIncomingCallProp = (
|
||||
const mapStateToRingingCallProp = (
|
||||
state: StateType
|
||||
): DirectIncomingCall | GroupIncomingCall | null => {
|
||||
const call = getIncomingCall(state);
|
||||
if (!call) {
|
||||
const ourAci = getUserACI(state);
|
||||
const ringingCall = getRingingCall(state);
|
||||
if (!ringingCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const conversation = getConversationSelector(state)(call.conversationId);
|
||||
const conversation = getConversationSelector(state)(
|
||||
ringingCall.conversationId
|
||||
);
|
||||
if (!conversation) {
|
||||
log.error('The incoming call has no corresponding conversation');
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (call.callMode) {
|
||||
switch (ringingCall.callMode) {
|
||||
case CallMode.Direct:
|
||||
return {
|
||||
callMode: CallMode.Direct as const,
|
||||
callState: call.callState,
|
||||
callEndedReason: call.callEndedReason,
|
||||
callState: ringingCall.callState,
|
||||
callEndedReason: ringingCall.callEndedReason,
|
||||
conversation,
|
||||
isVideoCall: call.isVideoCall,
|
||||
isVideoCall: ringingCall.isVideoCall,
|
||||
};
|
||||
case CallMode.Group: {
|
||||
if (!call.ringerAci) {
|
||||
log.error('The incoming group call has no ring state');
|
||||
if (getIsConversationTooBigToRing(conversation)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isLonelyGroup(conversation)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const conversationSelector = getConversationSelector(state);
|
||||
const ringer = conversationSelector(call.ringerAci);
|
||||
const ringer = conversationSelector(ringingCall.ringerAci || ourAci);
|
||||
const otherMembersRung = (conversation.sortedGroupMembers ?? []).filter(
|
||||
c => c.id !== ringer.id && !c.isMe
|
||||
);
|
||||
|
||||
return {
|
||||
callMode: CallMode.Group as const,
|
||||
connectionState: call.connectionState,
|
||||
joinState: call.joinState,
|
||||
connectionState: ringingCall.connectionState,
|
||||
joinState: ringingCall.joinState,
|
||||
conversation,
|
||||
otherMembersRung,
|
||||
ringer,
|
||||
remoteParticipants: call.remoteParticipants,
|
||||
remoteParticipants: ringingCall.remoteParticipants,
|
||||
};
|
||||
}
|
||||
case CallMode.Adhoc:
|
||||
log.error('Cannot handle an incoming adhoc call');
|
||||
return null;
|
||||
default:
|
||||
throw missingCaseError(call);
|
||||
throw missingCaseError(ringingCall);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -421,13 +428,10 @@ export const SmartCallManager = memo(function SmartCallManager() {
|
|||
const i18n = useSelector(getIntl);
|
||||
const activeCall = useSelector(mapStateToActiveCallProp);
|
||||
const callLink = useSelector(mapStateToCallLinkProp);
|
||||
const incomingCall = useSelector(mapStateToIncomingCallProp);
|
||||
const ringingCall = useSelector(mapStateToRingingCallProp);
|
||||
const availableCameras = useSelector(getAvailableCameras);
|
||||
const hasInitialLoadCompleted = useSelector(getHasInitialLoadCompleted);
|
||||
const me = useSelector(getMe);
|
||||
const isConversationTooBigToRing = incomingCall
|
||||
? getIsConversationTooBigToRing(incomingCall.conversation)
|
||||
: false;
|
||||
|
||||
const {
|
||||
approveUser,
|
||||
|
@ -493,8 +497,6 @@ export const SmartCallManager = memo(function SmartCallManager() {
|
|||
hangUpActiveCall={hangUpActiveCall}
|
||||
hasInitialLoadCompleted={hasInitialLoadCompleted}
|
||||
i18n={i18n}
|
||||
incomingCall={incomingCall}
|
||||
isConversationTooBigToRing={isConversationTooBigToRing}
|
||||
me={me}
|
||||
notifyForCall={notifyForCall}
|
||||
openSystemPreferencesAction={openSystemPreferencesAction}
|
||||
|
@ -504,6 +506,7 @@ export const SmartCallManager = memo(function SmartCallManager() {
|
|||
renderDeviceSelection={renderDeviceSelection}
|
||||
renderEmojiPicker={renderEmojiPicker}
|
||||
renderReactionPicker={renderReactionPicker}
|
||||
ringingCall={ringingCall}
|
||||
sendGroupCallRaiseHand={sendGroupCallRaiseHand}
|
||||
sendGroupCallReaction={sendGroupCallReaction}
|
||||
selectPresentingSource={selectPresentingSource}
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
getCallsByConversation,
|
||||
getCallSelector,
|
||||
getHasAnyAdminCallLinks,
|
||||
getIncomingCall,
|
||||
getRingingCall,
|
||||
isInCall,
|
||||
} from '../../../state/selectors/calling';
|
||||
import type {
|
||||
|
@ -181,15 +181,15 @@ describe('state/selectors/calling', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('getIncomingCall', () => {
|
||||
describe('getRingingCall', () => {
|
||||
it('returns undefined if there are no calls', () => {
|
||||
assert.isUndefined(getIncomingCall(getEmptyRootState()));
|
||||
assert.isUndefined(getRingingCall(getEmptyRootState()));
|
||||
});
|
||||
|
||||
it('returns undefined if there is no incoming call', () => {
|
||||
assert.isUndefined(getIncomingCall(getCallingState(stateWithDirectCall)));
|
||||
assert.isUndefined(getRingingCall(getCallingState(stateWithDirectCall)));
|
||||
assert.isUndefined(
|
||||
getIncomingCall(getCallingState(stateWithActiveDirectCall))
|
||||
getRingingCall(getCallingState(stateWithActiveDirectCall))
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -209,19 +209,19 @@ describe('state/selectors/calling', () => {
|
|||
},
|
||||
};
|
||||
|
||||
assert.isUndefined(getIncomingCall(getCallingState(state)));
|
||||
assert.isUndefined(getRingingCall(getCallingState(state)));
|
||||
});
|
||||
|
||||
it('returns an incoming direct call', () => {
|
||||
assert.deepEqual(
|
||||
getIncomingCall(getCallingState(stateWithIncomingDirectCall)),
|
||||
getRingingCall(getCallingState(stateWithIncomingDirectCall)),
|
||||
incomingDirectCall
|
||||
);
|
||||
});
|
||||
|
||||
it('returns an incoming group call', () => {
|
||||
assert.deepEqual(
|
||||
getIncomingCall(getCallingState(stateWithIncomingGroupCall)),
|
||||
getRingingCall(getCallingState(stateWithIncomingGroupCall)),
|
||||
incomingGroupCall
|
||||
);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue