| 
									
										
										
										
											2023-01-03 11:55:46 -08:00
										 |  |  | // Copyright 2020 Signal Messenger, LLC
 | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  | // SPDX-License-Identifier: AGPL-3.0-only
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-26 14:15:33 -05:00
										 |  |  | import type { LocalizerType } from '../types/Util'; | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  | import { | 
					
						
							| 
									
										
										
										
											2024-08-06 12:29:13 -07:00
										 |  |  |   CallMode, | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   CallDirection, | 
					
						
							|  |  |  |   DirectCallStatus, | 
					
						
							|  |  |  |   type CallHistoryDetails, | 
					
						
							|  |  |  |   CallType, | 
					
						
							| 
									
										
										
										
											2024-07-30 16:21:33 -07:00
										 |  |  |   GroupCallStatus, | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  | } from '../types/CallDisposition'; | 
					
						
							| 
									
										
										
										
											2024-08-06 12:29:13 -07:00
										 |  |  | import { missingCaseError } from './missingCaseError'; | 
					
						
							|  |  |  | import type { CallStatus } from '../types/CallDisposition'; | 
					
						
							| 
									
										
										
										
											2023-01-12 15:29:07 -08:00
										 |  |  | import type { ConversationType } from '../state/ducks/conversations'; | 
					
						
							| 
									
										
										
										
											2023-08-21 10:09:54 -07:00
										 |  |  | import { strictAssert } from './assert'; | 
					
						
							| 
									
										
										
										
											2024-07-30 16:21:33 -07:00
										 |  |  | import { isMoreRecentThan } from './timestamp'; | 
					
						
							|  |  |  | import { MINUTE } from './durations'; | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  | export type CallingNotificationType = Readonly<{ | 
					
						
							| 
									
										
										
										
											2023-08-16 17:11:09 -07:00
										 |  |  |   // In some older calls, we don't have a call id, this hardens against that.
 | 
					
						
							|  |  |  |   callHistory: CallHistoryDetails | null; | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   callCreator: ConversationType | null; | 
					
						
							| 
									
										
										
										
											2023-08-21 10:09:54 -07:00
										 |  |  |   activeConversationId: string | null; | 
					
						
							|  |  |  |   groupCallEnded: boolean | null; | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |   deviceCount: number; | 
					
						
							|  |  |  |   maxDevices: number; | 
					
						
							| 
									
										
										
										
											2023-12-12 11:11:39 -05:00
										 |  |  |   isSelectMode: boolean; | 
					
						
							|  |  |  |   isTargeted: boolean; | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  | }>; | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-30 16:21:33 -07:00
										 |  |  | export function getDirectCallNotificationText( | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   callDirection: CallDirection, | 
					
						
							|  |  |  |   callType: CallType, | 
					
						
							|  |  |  |   callStatus: DirectCallStatus, | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |   i18n: LocalizerType | 
					
						
							|  |  |  | ): string { | 
					
						
							| 
									
										
										
										
											2024-08-14 04:39:04 +10:00
										 |  |  |   if ( | 
					
						
							|  |  |  |     callStatus === DirectCallStatus.Pending || | 
					
						
							|  |  |  |     callStatus === DirectCallStatus.Unknown | 
					
						
							|  |  |  |   ) { | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |     if (callDirection === CallDirection.Incoming) { | 
					
						
							|  |  |  |       return callType === CallType.Video | 
					
						
							|  |  |  |         ? i18n('icu:incomingVideoCall') | 
					
						
							|  |  |  |         : i18n('icu:incomingAudioCall'); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |     return callType === CallType.Video | 
					
						
							|  |  |  |       ? i18n('icu:outgoingVideoCall') | 
					
						
							|  |  |  |       : i18n('icu:outgoingAudioCall'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (callStatus === DirectCallStatus.Accepted) { | 
					
						
							|  |  |  |     if (callDirection === CallDirection.Incoming) { | 
					
						
							|  |  |  |       return callType === CallType.Video | 
					
						
							|  |  |  |         ? i18n('icu:acceptedIncomingVideoCall') | 
					
						
							|  |  |  |         : i18n('icu:acceptedIncomingAudioCall'); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |     return callType === CallType.Video | 
					
						
							|  |  |  |       ? i18n('icu:acceptedOutgoingVideoCall') | 
					
						
							|  |  |  |       : i18n('icu:acceptedOutgoingAudioCall'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (callStatus === DirectCallStatus.Declined) { | 
					
						
							|  |  |  |     if (callDirection === CallDirection.Incoming) { | 
					
						
							|  |  |  |       return callType === CallType.Video | 
					
						
							|  |  |  |         ? i18n('icu:declinedIncomingVideoCall') | 
					
						
							|  |  |  |         : i18n('icu:declinedIncomingAudioCall'); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |     return callType === CallType.Video | 
					
						
							|  |  |  |       ? i18n('icu:missedOrDeclinedOutgoingVideoCall') | 
					
						
							|  |  |  |       : i18n('icu:missedOrDeclinedOutgoingAudioCall'); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-14 04:39:04 +10:00
										 |  |  |   if ( | 
					
						
							|  |  |  |     callStatus === DirectCallStatus.Missed || | 
					
						
							|  |  |  |     callStatus === DirectCallStatus.MissedNotificationProfile | 
					
						
							|  |  |  |   ) { | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |     if (callDirection === CallDirection.Incoming) { | 
					
						
							|  |  |  |       return callType === CallType.Video | 
					
						
							|  |  |  |         ? i18n('icu:missedIncomingVideoCall') | 
					
						
							|  |  |  |         : i18n('icu:missedIncomingAudioCall'); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |     return callType === CallType.Video | 
					
						
							|  |  |  |       ? i18n('icu:missedOrDeclinedOutgoingVideoCall') | 
					
						
							|  |  |  |       : i18n('icu:missedOrDeclinedOutgoingAudioCall'); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (callStatus === DirectCallStatus.Deleted) { | 
					
						
							|  |  |  |     throw new Error( | 
					
						
							|  |  |  |       'getDirectCallNotificationText: Cannot render deleted call' | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   throw missingCaseError(callStatus); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-30 16:21:33 -07:00
										 |  |  | function getGroupCallNotificationText({ | 
					
						
							|  |  |  |   groupCallEnded, | 
					
						
							|  |  |  |   creator, | 
					
						
							|  |  |  |   callHistory, | 
					
						
							|  |  |  |   i18n, | 
					
						
							|  |  |  | }: { | 
					
						
							|  |  |  |   groupCallEnded: boolean; | 
					
						
							|  |  |  |   creator: ConversationType | null; | 
					
						
							|  |  |  |   callHistory: CallHistoryDetails; | 
					
						
							|  |  |  |   i18n: LocalizerType; | 
					
						
							|  |  |  | }): string { | 
					
						
							| 
									
										
										
										
											2023-08-21 10:09:54 -07:00
										 |  |  |   if (groupCallEnded) { | 
					
						
							| 
									
										
										
										
											2024-07-30 16:21:33 -07:00
										 |  |  |     const { direction, status, timestamp } = callHistory; | 
					
						
							|  |  |  |     if (direction === CallDirection.Incoming) { | 
					
						
							|  |  |  |       if (status === GroupCallStatus.Declined) { | 
					
						
							|  |  |  |         return i18n('icu:CallHistory__DescriptionVideoCall--Declined'); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (status === GroupCallStatus.Missed) { | 
					
						
							|  |  |  |         return i18n('icu:CallHistory__DescriptionVideoCall--Missed'); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (isMoreRecentThan(timestamp, 5 * MINUTE)) { | 
					
						
							|  |  |  |         return i18n('icu:calling__call-notification__ended'); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return i18n('icu:acceptedIncomingVideoCall'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Outgoing ended group calls
 | 
					
						
							|  |  |  |     if (isMoreRecentThan(timestamp, 5 * MINUTE)) { | 
					
						
							|  |  |  |       return i18n('icu:calling__call-notification__ended'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return i18n('icu:acceptedOutgoingVideoCall'); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-07-30 16:21:33 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // TODO: Active call with participants DESKTOP-7439
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   if (creator == null) { | 
					
						
							| 
									
										
										
										
											2023-03-29 17:03:25 -07:00
										 |  |  |     return i18n('icu:calling__call-notification__started-by-someone'); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   if (creator.isMe) { | 
					
						
							| 
									
										
										
										
											2023-03-29 17:03:25 -07:00
										 |  |  |     return i18n('icu:calling__call-notification__started-by-you'); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-29 17:03:25 -07:00
										 |  |  |   return i18n('icu:calling__call-notification__started', { | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |     name: creator.systemGivenName ?? creator.title, | 
					
						
							| 
									
										
										
										
											2023-03-27 16:37:39 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export function getCallingNotificationText( | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   callingNotification: CallingNotificationType, | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  |   i18n: LocalizerType | 
					
						
							| 
									
										
										
										
											2023-08-16 17:11:09 -07:00
										 |  |  | ): string | null { | 
					
						
							| 
									
										
										
										
											2024-07-30 16:21:33 -07:00
										 |  |  |   const { | 
					
						
							|  |  |  |     callHistory, | 
					
						
							|  |  |  |     callCreator: creator, | 
					
						
							|  |  |  |     groupCallEnded, | 
					
						
							|  |  |  |   } = callingNotification; | 
					
						
							| 
									
										
										
										
											2023-08-16 17:11:09 -07:00
										 |  |  |   if (callHistory == null) { | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   if (callHistory.mode === CallMode.Direct) { | 
					
						
							|  |  |  |     return getDirectCallNotificationText( | 
					
						
							|  |  |  |       callHistory.direction, | 
					
						
							|  |  |  |       callHistory.type, | 
					
						
							|  |  |  |       callHistory.status as DirectCallStatus, | 
					
						
							|  |  |  |       i18n | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (callHistory.mode === CallMode.Group) { | 
					
						
							| 
									
										
										
										
											2023-08-21 10:09:54 -07:00
										 |  |  |     strictAssert( | 
					
						
							|  |  |  |       groupCallEnded != null, | 
					
						
							|  |  |  |       'getCallingNotificationText: groupCallEnded shouldnt be null for a group call' | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2024-07-30 16:21:33 -07:00
										 |  |  |     return getGroupCallNotificationText({ | 
					
						
							|  |  |  |       groupCallEnded, | 
					
						
							|  |  |  |       creator, | 
					
						
							|  |  |  |       callHistory, | 
					
						
							|  |  |  |       i18n, | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-02-22 13:19:50 -08:00
										 |  |  |   if (callHistory.mode === CallMode.Adhoc) { | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   throw missingCaseError(callHistory.mode); | 
					
						
							| 
									
										
										
										
											2020-12-07 14:43:19 -06:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-08-26 16:51:55 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | type CallingIconType = | 
					
						
							|  |  |  |   | 'audio-incoming' | 
					
						
							|  |  |  |   | 'audio-missed' | 
					
						
							|  |  |  |   | 'audio-outgoing' | 
					
						
							|  |  |  |   | 'phone' | 
					
						
							|  |  |  |   | 'video' | 
					
						
							|  |  |  |   | 'video-incoming' | 
					
						
							|  |  |  |   | 'video-missed' | 
					
						
							|  |  |  |   | 'video-outgoing'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  | export function getCallingIcon( | 
					
						
							|  |  |  |   callType: CallType, | 
					
						
							|  |  |  |   callDirection: CallDirection, | 
					
						
							|  |  |  |   callStatus: CallStatus | 
					
						
							|  |  |  | ): CallingIconType { | 
					
						
							|  |  |  |   if (callType === CallType.Audio) { | 
					
						
							|  |  |  |     if (callStatus === DirectCallStatus.Accepted) { | 
					
						
							|  |  |  |       return callDirection === CallDirection.Incoming | 
					
						
							|  |  |  |         ? 'audio-incoming' | 
					
						
							|  |  |  |         : 'audio-outgoing'; | 
					
						
							| 
									
										
										
										
											2021-08-26 16:51:55 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |     if ( | 
					
						
							|  |  |  |       callStatus === DirectCallStatus.Missed || | 
					
						
							|  |  |  |       callStatus === DirectCallStatus.Declined | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |       return 'audio-missed'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 'phone'; | 
					
						
							| 
									
										
										
										
											2021-08-26 16:51:55 -04:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   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'; | 
					
						
							| 
									
										
										
										
											2021-08-26 16:51:55 -04:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-04-25 10:09:05 -07:00
										 |  |  |   if (callType === CallType.Group || callType === CallType.Adhoc) { | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |     return 'video'; | 
					
						
							| 
									
										
										
										
											2021-08-26 16:51:55 -04:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-08-14 04:39:04 +10:00
										 |  |  |   if (callType === CallType.Unknown) { | 
					
						
							|  |  |  |     return 'video'; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-08-08 17:53:06 -07:00
										 |  |  |   throw missingCaseError(callType); | 
					
						
							| 
									
										
										
										
											2021-08-26 16:51:55 -04:00
										 |  |  | } |