Add additional checks/logs to ringtones
This commit is contained in:
parent
93e61a1a3a
commit
422ebf1bc8
3 changed files with 102 additions and 32 deletions
|
@ -73,6 +73,7 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
getPresentingSources: action('get-presenting-sources'),
|
getPresentingSources: action('get-presenting-sources'),
|
||||||
hangUpActiveCall: action('hang-up-active-call'),
|
hangUpActiveCall: action('hang-up-active-call'),
|
||||||
i18n,
|
i18n,
|
||||||
|
incomingCall: null,
|
||||||
isGroupCallRaiseHandEnabled: true,
|
isGroupCallRaiseHandEnabled: true,
|
||||||
isGroupCallReactionsEnabled: true,
|
isGroupCallReactionsEnabled: true,
|
||||||
keyChangeOk: action('key-change-ok'),
|
keyChangeOk: action('key-change-ok'),
|
||||||
|
@ -189,6 +190,8 @@ export function RingingGroupCall(): JSX.Element {
|
||||||
{...createProps({
|
{...createProps({
|
||||||
incomingCall: {
|
incomingCall: {
|
||||||
callMode: CallMode.Group as const,
|
callMode: CallMode.Group as const,
|
||||||
|
connectionState: GroupCallConnectionState.NotConnected,
|
||||||
|
joinState: GroupCallJoinState.NotJoined,
|
||||||
conversation: {
|
conversation: {
|
||||||
...getConversation(),
|
...getConversation(),
|
||||||
type: 'group',
|
type: 'group',
|
||||||
|
@ -201,6 +204,7 @@ export function RingingGroupCall(): JSX.Element {
|
||||||
{ firstName: 'Summer', title: 'Summer Smith' },
|
{ firstName: 'Summer', title: 'Summer Smith' },
|
||||||
],
|
],
|
||||||
ringer: { firstName: 'Rick', title: 'Rick Sanchez' },
|
ringer: { firstName: 'Rick', title: 'Rick Sanchez' },
|
||||||
|
remoteParticipants: [],
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -32,6 +32,7 @@ import type {
|
||||||
AcceptCallType,
|
AcceptCallType,
|
||||||
CancelCallType,
|
CancelCallType,
|
||||||
DeclineCallType,
|
DeclineCallType,
|
||||||
|
GroupCallParticipantInfoType,
|
||||||
KeyChangeOkType,
|
KeyChangeOkType,
|
||||||
SendGroupCallRaiseHandType,
|
SendGroupCallRaiseHandType,
|
||||||
SendGroupCallReactionType,
|
SendGroupCallReactionType,
|
||||||
|
@ -47,9 +48,28 @@ import { missingCaseError } from '../util/missingCaseError';
|
||||||
import { CallingToastProvider } from './CallingToast';
|
import { CallingToastProvider } from './CallingToast';
|
||||||
import type { SmartReactionPicker } from '../state/smart/ReactionPicker';
|
import type { SmartReactionPicker } from '../state/smart/ReactionPicker';
|
||||||
import type { Props as ReactionPickerProps } from './conversation/ReactionPicker';
|
import type { Props as ReactionPickerProps } from './conversation/ReactionPicker';
|
||||||
|
import * as log from '../logging/log';
|
||||||
|
|
||||||
const GROUP_CALL_RING_DURATION = 60 * 1000;
|
const GROUP_CALL_RING_DURATION = 60 * 1000;
|
||||||
|
|
||||||
|
export type DirectIncomingCall = Readonly<{
|
||||||
|
callMode: CallMode.Direct;
|
||||||
|
callState?: CallState;
|
||||||
|
callEndedReason?: CallEndedReason;
|
||||||
|
conversation: ConversationType;
|
||||||
|
isVideoCall: boolean;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type GroupIncomingCall = Readonly<{
|
||||||
|
callMode: CallMode.Group;
|
||||||
|
connectionState: GroupCallConnectionState;
|
||||||
|
joinState: GroupCallJoinState;
|
||||||
|
conversation: ConversationType;
|
||||||
|
otherMembersRung: Array<Pick<ConversationType, 'firstName' | 'title'>>;
|
||||||
|
ringer: Pick<ConversationType, 'firstName' | 'title'>;
|
||||||
|
remoteParticipants: Array<GroupCallParticipantInfoType>;
|
||||||
|
}>;
|
||||||
|
|
||||||
export type PropsType = {
|
export type PropsType = {
|
||||||
activeCall?: ActiveCallType;
|
activeCall?: ActiveCallType;
|
||||||
availableCameras: Array<MediaDeviceInfo>;
|
availableCameras: Array<MediaDeviceInfo>;
|
||||||
|
@ -62,18 +82,7 @@ export type PropsType = {
|
||||||
) => VideoFrameSource;
|
) => VideoFrameSource;
|
||||||
getPreferredBadge: PreferredBadgeSelectorType;
|
getPreferredBadge: PreferredBadgeSelectorType;
|
||||||
getPresentingSources: () => void;
|
getPresentingSources: () => void;
|
||||||
incomingCall?:
|
incomingCall: DirectIncomingCall | GroupIncomingCall | null;
|
||||||
| {
|
|
||||||
callMode: CallMode.Direct;
|
|
||||||
conversation: ConversationType;
|
|
||||||
isVideoCall: boolean;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
callMode: CallMode.Group;
|
|
||||||
conversation: ConversationType;
|
|
||||||
otherMembersRung: Array<Pick<ConversationType, 'firstName' | 'title'>>;
|
|
||||||
ringer: Pick<ConversationType, 'firstName' | 'title'>;
|
|
||||||
};
|
|
||||||
keyChangeOk: (_: KeyChangeOkType) => void;
|
keyChangeOk: (_: KeyChangeOkType) => void;
|
||||||
renderDeviceSelection: () => JSX.Element;
|
renderDeviceSelection: () => JSX.Element;
|
||||||
renderReactionPicker: (
|
renderReactionPicker: (
|
||||||
|
@ -431,8 +440,10 @@ export function CallManager(props: PropsType): JSX.Element | null {
|
||||||
const shouldRing = getShouldRing(props);
|
const shouldRing = getShouldRing(props);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (shouldRing) {
|
if (shouldRing) {
|
||||||
|
log.info('CallManager: Playing ringtone');
|
||||||
playRingtone();
|
playRingtone();
|
||||||
return () => {
|
return () => {
|
||||||
|
log.info('CallManager: Stopping ringtone');
|
||||||
stopRingtone();
|
stopRingtone();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -486,6 +497,31 @@ export function CallManager(props: PropsType): JSX.Element | null {
|
||||||
return null;
|
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: ConversationType): boolean {
|
||||||
|
return (conversation.sortedGroupMembers?.length ?? 0) < 2;
|
||||||
|
}
|
||||||
|
|
||||||
function getShouldRing({
|
function getShouldRing({
|
||||||
activeCall,
|
activeCall,
|
||||||
incomingCall,
|
incomingCall,
|
||||||
|
@ -493,35 +529,54 @@ function getShouldRing({
|
||||||
}: Readonly<
|
}: Readonly<
|
||||||
Pick<PropsType, 'activeCall' | 'incomingCall' | 'isConversationTooBigToRing'>
|
Pick<PropsType, 'activeCall' | 'incomingCall' | 'isConversationTooBigToRing'>
|
||||||
>): boolean {
|
>): boolean {
|
||||||
if (incomingCall) {
|
if (incomingCall != null) {
|
||||||
// don't ring a large group
|
// don't ring a large group
|
||||||
if (isConversationTooBigToRing) {
|
if (isConversationTooBigToRing) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !activeCall;
|
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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw missingCaseError(incomingCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!activeCall) {
|
if (activeCall != null) {
|
||||||
return false;
|
if (activeCall.callMode === CallMode.Direct) {
|
||||||
}
|
|
||||||
|
|
||||||
switch (activeCall.callMode) {
|
|
||||||
case CallMode.Direct:
|
|
||||||
return (
|
return (
|
||||||
activeCall.callState === CallState.Prering ||
|
activeCall.callState === CallState.Prering ||
|
||||||
activeCall.callState === CallState.Ringing
|
activeCall.callState === CallState.Ringing
|
||||||
);
|
);
|
||||||
case CallMode.Group:
|
}
|
||||||
|
|
||||||
|
if (activeCall.callMode === CallMode.Group) {
|
||||||
return (
|
return (
|
||||||
activeCall.outgoingRing &&
|
activeCall.outgoingRing &&
|
||||||
(activeCall.connectionState === GroupCallConnectionState.Connecting ||
|
isConnected(activeCall.connectionState) &&
|
||||||
activeCall.connectionState === GroupCallConnectionState.Connected) &&
|
isJoined(activeCall.joinState) &&
|
||||||
activeCall.joinState !== GroupCallJoinState.NotJoined &&
|
!hasRemoteParticipants(activeCall.remoteParticipants) &&
|
||||||
!activeCall.remoteParticipants.length &&
|
!isLonelyGroup(activeCall.conversation)
|
||||||
(activeCall.conversation.sortedGroupMembers || []).length >= 2
|
|
||||||
);
|
);
|
||||||
default:
|
}
|
||||||
throw missingCaseError(activeCall);
|
|
||||||
|
throw missingCaseError(activeCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,10 @@ import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { memoize } from 'lodash';
|
import { memoize } from 'lodash';
|
||||||
import { mapDispatchToProps } from '../actions';
|
import { mapDispatchToProps } from '../actions';
|
||||||
|
import type {
|
||||||
|
DirectIncomingCall,
|
||||||
|
GroupIncomingCall,
|
||||||
|
} from '../../components/CallManager';
|
||||||
import { CallManager } from '../../components/CallManager';
|
import { CallManager } from '../../components/CallManager';
|
||||||
import { calling as callingService } from '../../services/calling';
|
import { calling as callingService } from '../../services/calling';
|
||||||
import { getIntl, getTheme } from '../selectors/user';
|
import { getIntl, getTheme } from '../selectors/user';
|
||||||
|
@ -320,29 +324,33 @@ const mapStateToActiveCallProp = (
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToIncomingCallProp = (state: StateType) => {
|
const mapStateToIncomingCallProp = (
|
||||||
|
state: StateType
|
||||||
|
): DirectIncomingCall | GroupIncomingCall | null => {
|
||||||
const call = getIncomingCall(state);
|
const call = getIncomingCall(state);
|
||||||
if (!call) {
|
if (!call) {
|
||||||
return undefined;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const conversation = getConversationSelector(state)(call.conversationId);
|
const conversation = getConversationSelector(state)(call.conversationId);
|
||||||
if (!conversation) {
|
if (!conversation) {
|
||||||
log.error('The incoming call has no corresponding conversation');
|
log.error('The incoming call has no corresponding conversation');
|
||||||
return undefined;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (call.callMode) {
|
switch (call.callMode) {
|
||||||
case CallMode.Direct:
|
case CallMode.Direct:
|
||||||
return {
|
return {
|
||||||
callMode: CallMode.Direct as const,
|
callMode: CallMode.Direct as const,
|
||||||
|
callState: call.callState,
|
||||||
|
callEndedReason: call.callEndedReason,
|
||||||
conversation,
|
conversation,
|
||||||
isVideoCall: call.isVideoCall,
|
isVideoCall: call.isVideoCall,
|
||||||
};
|
};
|
||||||
case CallMode.Group: {
|
case CallMode.Group: {
|
||||||
if (!call.ringerAci) {
|
if (!call.ringerAci) {
|
||||||
log.error('The incoming group call has no ring state');
|
log.error('The incoming group call has no ring state');
|
||||||
return undefined;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const conversationSelector = getConversationSelector(state);
|
const conversationSelector = getConversationSelector(state);
|
||||||
|
@ -353,9 +361,12 @@ const mapStateToIncomingCallProp = (state: StateType) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
callMode: CallMode.Group as const,
|
callMode: CallMode.Group as const,
|
||||||
|
connectionState: call.connectionState,
|
||||||
|
joinState: call.joinState,
|
||||||
conversation,
|
conversation,
|
||||||
otherMembersRung,
|
otherMembersRung,
|
||||||
ringer,
|
ringer,
|
||||||
|
remoteParticipants: call.remoteParticipants,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue