Calls Tab & Group Call Disposition

This commit is contained in:
Jamie Kyle 2023-08-08 17:53:06 -07:00 committed by GitHub
parent 620e85ca01
commit 1eaabb6734
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
139 changed files with 9182 additions and 2721 deletions

View file

@ -4,110 +4,131 @@
import type { LocalizerType } from '../types/Util';
import { CallMode } from '../types/Calling';
import { missingCaseError } from './missingCaseError';
import * as log from '../logging/log';
import type { CallStatus } from '../types/CallDisposition';
import {
CallDirection,
DirectCallStatus,
type CallHistoryDetails,
CallType,
} from '../types/CallDisposition';
import type { ConversationType } from '../state/ducks/conversations';
type DirectCallNotificationType = {
callMode: CallMode.Direct;
activeCallConversationId?: string;
wasIncoming: boolean;
wasVideoCall: boolean;
wasDeclined: boolean;
acceptedTime?: number;
endedTime?: number;
};
export enum CallExternalState {
Active,
Full,
Joined,
Ended,
InOtherCall,
}
type GroupCallNotificationType = {
activeCallConversationId?: string;
callMode: CallMode.Group;
conversationId: string;
creator?: ConversationType;
ended: boolean;
export type CallingNotificationType = Readonly<{
callHistory: CallHistoryDetails;
callCreator: ConversationType | null;
callExternalState: CallExternalState;
deviceCount: number;
maxDevices: number;
startedTime: number;
};
export type CallingNotificationType =
| DirectCallNotificationType
| GroupCallNotificationType;
}>;
function getDirectCallNotificationText(
{
wasIncoming,
wasVideoCall,
wasDeclined,
acceptedTime,
}: DirectCallNotificationType,
callDirection: CallDirection,
callType: CallType,
callStatus: DirectCallStatus,
i18n: LocalizerType
): string {
const wasAccepted = Boolean(acceptedTime);
if (callStatus === DirectCallStatus.Pending) {
if (callDirection === CallDirection.Incoming) {
return callType === CallType.Video
? i18n('icu:incomingVideoCall')
: i18n('icu:incomingAudioCall');
}
return callType === CallType.Video
? i18n('icu:outgoingVideoCall')
: i18n('icu:outgoingAudioCall');
}
if (wasIncoming) {
if (wasDeclined) {
if (wasVideoCall) {
return i18n('icu:declinedIncomingVideoCall');
}
return i18n('icu:declinedIncomingAudioCall');
if (callStatus === DirectCallStatus.Accepted) {
if (callDirection === CallDirection.Incoming) {
return callType === CallType.Video
? i18n('icu:acceptedIncomingVideoCall')
: i18n('icu:acceptedIncomingAudioCall');
}
if (wasAccepted) {
if (wasVideoCall) {
return i18n('icu:acceptedIncomingVideoCall');
}
return i18n('icu:acceptedIncomingAudioCall');
}
if (wasVideoCall) {
return i18n('icu:missedIncomingVideoCall');
}
return i18n('icu:missedIncomingAudioCall');
return callType === CallType.Video
? i18n('icu:acceptedOutgoingVideoCall')
: i18n('icu:acceptedOutgoingAudioCall');
}
if (wasAccepted) {
if (wasVideoCall) {
return i18n('icu:acceptedOutgoingVideoCall');
if (callStatus === DirectCallStatus.Declined) {
if (callDirection === CallDirection.Incoming) {
return callType === CallType.Video
? i18n('icu:declinedIncomingVideoCall')
: i18n('icu:declinedIncomingAudioCall');
}
return i18n('icu:acceptedOutgoingAudioCall');
return callType === CallType.Video
? i18n('icu:missedOrDeclinedOutgoingVideoCall')
: i18n('icu:missedOrDeclinedOutgoingAudioCall');
}
if (wasVideoCall) {
return i18n('icu:missedOrDeclinedOutgoingVideoCall');
if (callStatus === DirectCallStatus.Missed) {
if (callDirection === CallDirection.Incoming) {
return callType === CallType.Video
? i18n('icu:missedIncomingVideoCall')
: i18n('icu:missedIncomingAudioCall');
}
return callType === CallType.Video
? i18n('icu:missedOrDeclinedOutgoingVideoCall')
: i18n('icu:missedOrDeclinedOutgoingAudioCall');
}
return i18n('icu:missedOrDeclinedOutgoingAudioCall');
if (callStatus === DirectCallStatus.Deleted) {
throw new Error(
'getDirectCallNotificationText: Cannot render deleted call'
);
}
throw missingCaseError(callStatus);
}
function getGroupCallNotificationText(
notification: GroupCallNotificationType,
callExternalState: CallExternalState,
creator: ConversationType | null,
i18n: LocalizerType
): string {
if (notification.ended) {
if (callExternalState === CallExternalState.Ended) {
return i18n('icu:calling__call-notification__ended');
}
if (!notification.creator) {
if (creator == null) {
return i18n('icu:calling__call-notification__started-by-someone');
}
if (notification.creator.isMe) {
if (creator.isMe) {
return i18n('icu:calling__call-notification__started-by-you');
}
return i18n('icu:calling__call-notification__started', {
name: notification.creator.systemGivenName ?? notification.creator.title,
name: creator.systemGivenName ?? creator.title,
});
}
export function getCallingNotificationText(
notification: CallingNotificationType,
callingNotification: CallingNotificationType,
i18n: LocalizerType
): string {
switch (notification.callMode) {
case CallMode.Direct:
return getDirectCallNotificationText(notification, i18n);
case CallMode.Group:
return getGroupCallNotificationText(notification, i18n);
default:
log.error(
`getCallingNotificationText: missing case ${missingCaseError(
notification
)}`
);
return '';
const { callHistory, callCreator, callExternalState } = callingNotification;
if (callHistory.mode === CallMode.Direct) {
return getDirectCallNotificationText(
callHistory.direction,
callHistory.type,
callHistory.status as DirectCallStatus,
i18n
);
}
if (callHistory.mode === CallMode.Group) {
return getGroupCallNotificationText(callExternalState, callCreator, i18n);
}
if (callHistory.mode === CallMode.None) {
throw new Error(
'getCallingNotificationText: Cannot render call history details with mode = None'
);
}
throw missingCaseError(callHistory.mode);
}
type CallingIconType =
@ -120,42 +141,41 @@ type CallingIconType =
| 'video-missed'
| 'video-outgoing';
function getDirectCallingIcon({
wasIncoming,
wasVideoCall,
acceptedTime,
}: DirectCallNotificationType): CallingIconType {
const wasAccepted = Boolean(acceptedTime);
// video
if (wasVideoCall) {
if (wasAccepted) {
return wasIncoming ? 'video-incoming' : 'video-outgoing';
}
return 'video-missed';
}
if (wasAccepted) {
return wasIncoming ? 'audio-incoming' : 'audio-outgoing';
}
return 'audio-missed';
}
export function getCallingIcon(
notification: CallingNotificationType
callType: CallType,
callDirection: CallDirection,
callStatus: CallStatus
): CallingIconType {
switch (notification.callMode) {
case CallMode.Direct:
return getDirectCallingIcon(notification);
case CallMode.Group:
return 'video';
default:
log.error(
`getCallingNotificationText: missing case ${missingCaseError(
notification
)}`
);
return 'phone';
if (callType === CallType.Audio) {
if (callStatus === DirectCallStatus.Accepted) {
return callDirection === CallDirection.Incoming
? 'audio-incoming'
: 'audio-outgoing';
}
if (
callStatus === DirectCallStatus.Missed ||
callStatus === DirectCallStatus.Declined
) {
return 'audio-missed';
}
return 'phone';
}
if (callType === CallType.Video) {
if (callStatus === DirectCallStatus.Accepted) {
return callDirection === CallDirection.Incoming
? 'video-incoming'
: 'video-outgoing';
}
if (
callStatus === DirectCallStatus.Missed ||
callStatus === DirectCallStatus.Declined
) {
return 'video-missed';
}
return 'video';
}
if (callType === CallType.Group) {
return 'video';
}
throw missingCaseError(callType);
}