// Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import type { ReactNode } from 'react'; import React from 'react'; import { noop } from 'lodash'; import { SystemMessage, SystemMessageKind } from './SystemMessage'; import { Button, ButtonSize, ButtonVariant } from '../Button'; import { MessageTimestamp } from './MessageTimestamp'; import type { LocalizerType } from '../../types/Util'; import { CallMode } from '../../types/Calling'; import type { CallingNotificationType } from '../../util/callingNotification'; import { CallExternalState, getCallingIcon, getCallingNotificationText, } from '../../util/callingNotification'; import { missingCaseError } from '../../util/missingCaseError'; import { Tooltip, TooltipPlacement } from '../Tooltip'; import * as log from '../../logging/log'; import { CallDirection, CallType, DirectCallStatus, GroupCallStatus, } from '../../types/CallDisposition'; export type PropsActionsType = { returnToActiveCall: () => void; startCallingLobby: (_: { conversationId: string; isVideoCall: boolean; }) => void; }; type PropsHousekeeping = { i18n: LocalizerType; conversationId: string; isNextItemCallingNotification: boolean; }; export type PropsType = CallingNotificationType & PropsActionsType & PropsHousekeeping; export const CallingNotification: React.FC = React.memo( function CallingNotificationInner(props) { const { i18n } = props; const { type, direction, status, timestamp } = props.callHistory; const icon = getCallingIcon(type, direction, status); return ( {getCallingNotificationText(props, i18n)} ·{' '} } icon={icon} kind={ status === DirectCallStatus.Missed || status === GroupCallStatus.Missed ? SystemMessageKind.Danger : SystemMessageKind.Normal } /> ); } ); function renderCallingNotificationButton( props: Readonly ): ReactNode { const { conversationId, i18n, isNextItemCallingNotification, returnToActiveCall, startCallingLobby, } = props; if (isNextItemCallingNotification) { return null; } let buttonText: string; let disabledTooltipText: undefined | string; let onClick: () => void; switch (props.callHistory.mode) { case CallMode.Direct: { const { direction, type } = props.callHistory; buttonText = direction === CallDirection.Incoming ? i18n('icu:calling__call-back') : i18n('icu:calling__call-again'); if ( props.callExternalState === CallExternalState.Joined || props.callExternalState === CallExternalState.InOtherCall ) { disabledTooltipText = i18n('icu:calling__in-another-call-tooltip'); onClick = noop; } else { onClick = () => { startCallingLobby({ conversationId, isVideoCall: type === CallType.Video, }); }; } break; } case CallMode.Group: { if (props.callExternalState === CallExternalState.Ended) { return null; } if (props.callExternalState === CallExternalState.Joined) { buttonText = i18n('icu:calling__return'); onClick = returnToActiveCall; } else if (props.callExternalState === CallExternalState.InOtherCall) { buttonText = i18n('icu:calling__join'); disabledTooltipText = i18n('icu:calling__in-another-call-tooltip'); onClick = noop; } else if (props.callExternalState === CallExternalState.Full) { buttonText = i18n('icu:calling__call-is-full'); disabledTooltipText = i18n( 'icu:calling__call-notification__button__call-full-tooltip', { max: props.maxDevices, } ); onClick = noop; } else if (props.callExternalState === CallExternalState.Active) { buttonText = i18n('icu:calling__join'); onClick = () => { startCallingLobby({ conversationId, isVideoCall: true }); }; } else { throw missingCaseError(props.callExternalState); } break; } case CallMode.None: { log.error('renderCallingNotificationButton: Call mode cant be none'); return null; } default: log.error(missingCaseError(props.callHistory.mode)); return null; } const button = ( ); if (disabledTooltipText) { return ( {button} ); } return button; }