@azure/communication-react 1.4.3-alpha-202212140016.0 → 1.4.3-alpha-202212160013.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/communication-react.d.ts +22 -0
  2. package/dist/dist-cjs/communication-react/index.js +726 -579
  3. package/dist/dist-cjs/communication-react/index.js.map +1 -1
  4. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
  5. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
  6. package/dist/dist-esm/calling-component-bindings/src/baseSelectors.d.ts +5 -0
  7. package/dist/dist-esm/calling-component-bindings/src/baseSelectors.js +8 -0
  8. package/dist/dist-esm/calling-component-bindings/src/baseSelectors.js.map +1 -1
  9. package/dist/dist-esm/calling-component-bindings/src/errorBarSelector.js +21 -10
  10. package/dist/dist-esm/calling-component-bindings/src/errorBarSelector.js.map +1 -1
  11. package/dist/dist-esm/react-components/src/components/DevicePermissions/DomainPermissions.d.ts +4 -0
  12. package/dist/dist-esm/react-components/src/components/DevicePermissions/DomainPermissions.js +9 -3
  13. package/dist/dist-esm/react-components/src/components/DevicePermissions/DomainPermissions.js.map +1 -1
  14. package/dist/dist-esm/react-components/src/components/ErrorBar.d.ts +8 -0
  15. package/dist/dist-esm/react-components/src/components/ErrorBar.js.map +1 -1
  16. package/dist/dist-esm/react-components/src/components/ParticipantsButton.d.ts +4 -0
  17. package/dist/dist-esm/react-components/src/components/ParticipantsButton.js +25 -4
  18. package/dist/dist-esm/react-components/src/components/ParticipantsButton.js.map +1 -1
  19. package/dist/dist-esm/react-components/src/components/utils.js +4 -0
  20. package/dist/dist-esm/react-components/src/components/utils.js.map +1 -1
  21. package/dist/dist-esm/react-components/src/localization/LocalizationProvider.d.ts +6 -0
  22. package/dist/dist-esm/react-components/src/localization/LocalizationProvider.js.map +1 -1
  23. package/dist/dist-esm/react-components/src/localization/locales/en-US/strings.json +22 -1
  24. package/dist/dist-esm/react-composites/src/composites/CallComposite/adapter/AzureCommunicationCallAdapter.js +4 -1
  25. package/dist/dist-esm/react-composites/src/composites/CallComposite/adapter/AzureCommunicationCallAdapter.js.map +1 -1
  26. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/CallArrangement.js +1 -1
  27. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/CallArrangement.js.map +1 -1
  28. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/CallReadinessModal.d.ts +3 -4
  29. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/CallReadinessModal.js +55 -24
  30. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/CallReadinessModal.js.map +1 -1
  31. package/dist/dist-esm/react-composites/src/composites/CallComposite/hooks/useAdaptedSelector.js +11 -3
  32. package/dist/dist-esm/react-composites/src/composites/CallComposite/hooks/useAdaptedSelector.js.map +1 -1
  33. package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/ConfigurationPage.js +27 -5
  34. package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/ConfigurationPage.js.map +1 -1
  35. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.d.ts +14 -0
  36. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.js +23 -1
  37. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.js.map +1 -1
  38. package/dist/dist-esm/react-composites/src/composites/ChatComposite/adapter/AzureCommunicationChatAdapter.js +4 -0
  39. package/dist/dist-esm/react-composites/src/composites/ChatComposite/adapter/AzureCommunicationChatAdapter.js.map +1 -1
  40. package/dist/dist-esm/react-composites/src/composites/common/AddPeopleButton.js +26 -3
  41. package/dist/dist-esm/react-composites/src/composites/common/AddPeopleButton.js.map +1 -1
  42. package/package.json +8 -8
@@ -202,7 +202,7 @@ const _toCommunicationIdentifier = (id) => {
202
202
  // Copyright (c) Microsoft Corporation.
203
203
  // Licensed under the MIT license.
204
204
  // GENERATED FILE. DO NOT EDIT MANUALLY.
205
- var telemetryVersion = '1.4.3-alpha-202212140016.0';
205
+ var telemetryVersion = '1.4.3-alpha-202212160013.0';
206
206
 
207
207
  // Copyright (c) Microsoft Corporation.
208
208
  /**
@@ -408,6 +408,13 @@ const getDiagnostics = (state, props) => { var _a; return (_a = state.calls[prop
408
408
  * @private
409
409
  */
410
410
  const getCallState = (state, props) => { var _a; return (_a = state.calls[props.callId]) === null || _a === void 0 ? void 0 : _a.state; };
411
+ /**
412
+ * @private
413
+ */
414
+ const getEnvironmentInfo = (state) => {
415
+ /* @conditional-compile-remove(unsupported-browser) */
416
+ return state.environmentInfo;
417
+ };
411
418
 
412
419
  // Copyright (c) Microsoft Corporation.
413
420
  // Licensed under the MIT license.
@@ -4003,7 +4010,7 @@ const typingIndicatorStringStyle = react.mergeStyles({
4003
4010
  wordBreak: 'break-word'
4004
4011
  });
4005
4012
 
4006
- var participantItem$d={isMeText:"(you)",menuTitle:"More Options",removeButtonLabel:"Remove",sharingIconLabel:"Sharing",mutedIconLabel:"Muted",displayNamePlaceholder:"Unnamed participant",participantStateConnecting:"Calling...",participantStateRinging:"Calling...",participantStateHold:"On hold"};var typingIndicator$d={singleUser:"{user} is typing ...",multipleUsers:"{users} are typing ...",multipleUsersAbbreviateOne:"{users} and 1 other are typing ...",multipleUsersAbbreviateMany:"{users} and {numOthers} others are typing ...",delimiter:", "};var sendBox$d={placeholderText:"Enter a message",textTooLong:"Your message length is over the maximum limit.",sendButtonAriaLabel:"Send message",fileUploadsPendingError:"Uploading... Please wait.",removeFile:"Remove file",uploading:"Uploading",uploadCompleted:"Upload completed"};var messageStatusIndicator$d={deliveredAriaLabel:"Message sent",deliveredTooltipText:"Sent",seenAriaLabel:"Message seen by others",seenTooltipText:"Seen",readByTooltipText:"Read by {messageThreadReadCount} of {remoteParticipantsCount}",sendingAriaLabel:"Message sending",sendingTooltipText:"Sending",failedToSendAriaLabel:"Message failed to send",failedToSendTooltipText:"Failed to send"};var endCallButton$d={label:"Leave",tooltipContent:"Leave call"};var cameraButton$d={onLabel:"Turn off",offLabel:"Turn on",tooltipDisabledContent:"Camera is disabled",tooltipOnContent:"Turn off camera",tooltipOffContent:"Turn on camera",tooltipVideoLoadingContent:"Video is loading",cameraMenuTitle:"Camera",cameraMenuTooltip:"Choose camera",cameraButtonSplitRoleDescription:"Split button",onSplitButtonAriaLabel:"Turn off camera and camera options",offSplitButtonAriaLabel:"Turn on camera and camera options",cameraActionTurnedOnAnnouncement:"Your camera has been turned on",cameraActionTurnedOffAnnouncement:"Your camera has been turned off"};var microphoneButton$d={onLabel:"Mute",offLabel:"Unmute",tooltipDisabledContent:"Microphone is disabled",tooltipOnContent:"Mute microphone",tooltipOffContent:"Unmute microphone",microphoneMenuTitle:"Microphone",microphoneMenuTooltip:"Choose microphone",speakerMenuTitle:"Speaker",speakerMenuTooltip:"Choose speaker",microphoneButtonSplitRoleDescription:"Split button",onSplitButtonAriaLabel:"Mute microphone and audio options",offSplitButtonAriaLabel:"Unmute microphone and audio options",microphoneActionTurnedOnAnnouncement:"Your microphone has been turned on",microphoneActionTurnedOffAnnouncement:"Your microphone has been turned off"};var devicesButton$d={label:"Devices",tooltipContent:"Manage devices",cameraMenuTitle:"Camera",cameraMenuTooltip:"Choose camera",audioDeviceMenuTitle:"Audio Device",audioDeviceMenuTooltip:"Choose audio device",microphoneMenuTitle:"Microphone",microphoneMenuTooltip:"Choose microphone",speakerMenuTitle:"Speaker",speakerMenuTooltip:"Choose speaker"};var participantsButton$d={label:"People",tooltipContent:"Show participants",menuHeader:"In this call",participantsListButtonLabel:"{numParticipants} people",muteAllButtonLabel:"Mute all",copyInviteLinkButtonLabel:"Copy invite link"};var screenShareButton$d={onLabel:"Stop presenting",offLabel:"Present",tooltipDisabledContent:"Presenting is disabled",tooltipOnContent:"Presenting your screen",tooltipOffContent:"Present your screen"};var messageThread$d={yesterday:"Yesterday",sunday:"Sunday",monday:"Monday",tuesday:"Tuesday",wednesday:"Wednesday",thursday:"Thursday",friday:"Friday",saturday:"Saturday",participantJoined:"joined the chat.",participantLeft:"left the chat.",editMessage:"Edit",removeMessage:"Delete",resendMessage:"Try sending again",failToSendTag:"Failed to send",editedTag:"Edited",liveAuthorIntro:"{author} says",messageContentAriaText:"{author} said {message}",messageContentMineAriaText:"You said {message}",editBoxTextLimit:"Your message is over the limit of {limitNumber} characters",editBoxPlaceholderText:"Edit your message",newMessagesIndicator:"New messages",noDisplayNameSub:"No name",editBoxCancelButton:"Cancel",editBoxSubmitButton:"Submit",messageReadCount:"Read by {messageReadByCount} of {remoteParticipantsCount}",actionMenuMoreOptions:"More Options",downloadFile:"Download file"};var errorBar$d={unableToReachChatService:"You are offline",accessDenied:"Unable to access chat services - please check the user credentials provided",userNotInChatThread:"You are no longer in this chat thread",sendMessageNotInChatThread:"Failed to send message because you are no longer in this chat thread",sendMessageGeneric:"Failed to send message",callingNetworkFailure:"Troubling connecting call - you seem to be offline",startVideoGeneric:"Failed to start video",stopVideoGeneric:"Failed to stop video",muteGeneric:"Failed to mute microphone",unmuteGeneric:"Failed to unmute microphone",speakingWhileMuted:"Your microphone is muted",startScreenShareGeneric:"Failed to start screen sharing",stopScreenShareGeneric:"Failed to stop screen sharing",callNetworkQualityLow:"Network quality is low.",callNoSpeakerFound:"No speakers or headphones found. Connect an audio device to hear the call.",callNoMicrophoneFound:"No microphones found. Connect an audio input device.",callMicrophoneAccessDenied:"Unable to access microphone. Click the lock in the address bar to grant permission to this webpage.",callMicrophoneMutedBySystem:"You are muted by your system.",callMicrophoneUnmutedBySystem:"Your microphone recovered and you were unmuted by your system.",callMacOsMicrophoneAccessDenied:"Unable to access microphone. Grant microphone permission in your macOS privacy settings.",callLocalVideoFreeze:"Network bandwidth is poor. Your video may appear paused for others on the call.",callCameraAccessDenied:"Unable to access camera. Click the lock in the address bar to grant permission to this webpage.",callCameraAlreadyInUse:"Unable to access camera. It may already be in use by another application.",callVideoStoppedBySystem:"Your video has been stopped by your system.",callVideoRecoveredBySystem:"Your video has resumed.",callMacOsCameraAccessDenied:"MacOS is blocking access to your camera. Update your privacy settings to allow this browser to access your camera.",callMacOsScreenShareAccessDenied:"MacOS is blocking screen sharing. Update your privacy settings to allow this browser to record your screen.",dismissButtonAriaLabel:"Close",failedToJoinCallGeneric:"Failed to join call.",failedToJoinCallInvalidMeetingLink:"Unable to join Meeting. Invalid Link."};var videoGallery$d={screenIsBeingSharedMessage:"You are sharing your screen",screenShareLoadingMessage:"Loading {participant}'s screen",localVideoLabel:"You",localVideoCameraSwitcherLabel:"Switch camera",localVideoMovementLabel:"Movable Local Video Tile",localVideoSelectedDescription:"{cameraName} selected",displayNamePlaceholder:"Unnamed participant",fitRemoteParticipantToFrame:"Fit to frame",fillRemoteParticipantFrame:"Fill frame"};var dialpad$d={placeholderText:"Enter phone number",deleteButtonAriaLabel:"Delete"};var holdButton$d={onLabel:"Resume",offLabel:"Hold",tooltipOnContent:"Resume call",tooltipOffContent:"Hold call"};var videoTile$d={participantStateConnecting:"Calling...",participantStateRinging:"Calling...",participantStateHold:"On hold"};var CameraAndMicrophoneDomainPermissionsRequest={primaryText:"Allow {appName} to use your camera and microphone",secondaryText:"This is so participants can see and hear you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without camera and microphone",ariaLabel:"Allow camera and microphone access"};var CameraDomainPermissionsRequest={primaryText:"Allow {appName} to use your camera",secondaryText:"This is so participants can see you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without camera",ariaLabel:"Allow camera access"};var MicrophoneDomainPermissionsRequest={primaryText:"Allow {appName} to use your microphone",secondaryText:"This is so participants can hear you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without microphone",ariaLabel:"Allow microphone access"};var CameraAndMicrophoneDomainPermissionsCheck={primaryText:"Checking for camera and microphone access",secondaryText:"Allow access if prompted. This is so participants can see and hear you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without camera and microphone",ariaLabel:"Checking for camera and microphone access. Allow access if prompted."};var CameraDomainPermissionsCheck={primaryText:"Checking for camera access",secondaryText:"Allow access if prompted. This is so participants can see you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without camera",ariaLabel:"Checking for camera access. Allow access if prompted."};var MicrophoneDomainPermissionsCheck={primaryText:"Checking for microphone access",secondaryText:"Allow access if prompted. This is so participants can hear you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without microphone",ariaLabel:"Checking for microphone access. Allow access if prompted."};var CameraAndMicrophoneDomainPermissionsDenied={primaryText:"Unable to access camera and microphone",secondaryText:"Click the lock icon in the address bar to grant microphone permissions to this webpage. A page refresh may be required.",primaryButtonText:"Continue without camera and microphone",linkText:"Need help? Get troubleshooting help"};var CameraDomainPermissionsDenied={primaryText:"Unable to access camera",secondaryText:"Click the lock icon in the address bar to grant camera permissions to this webpage. A page refresh may be required.",primaryButtonText:"Continue without camera",linkText:"Need help? Get troubleshooting help"};var MicrophoneDomainPermissionsDenied={primaryText:"Unable to access microphone",secondaryText:"Click the lock icon in the address bar to grant microphone permissions to this webpage. A page refresh may be required.",primaryButtonText:"Continue without microphone",linkText:"Need help? Get troubleshooting help"};var UnsupportedBrowser$e={primaryText:"Browser not supported",secondaryText:"Please join this call using a compatible browser.",moreHelpLinkText:"See compatibility requirements"};var UnsupportedBrowserVersion$1={primaryText:"Browser update needed",secondaryText:"To ensure the best call possible, please update your browser and then try joining the call again.",moreHelpLinkText:"See compatibility requirements",continueAnywayButtonText:"Start call without updating"};var UnsupportedOperatingSystem$1={primaryText:"Operating system not supported",secondaryText:"Please join this call using a device with a compatible operating system.",moreHelpLinkText:"See compatibility requirements"};var BrowserPermissionDenied$d={primaryText:"Can't use your camera or microphone",secondaryText:"Your browser might not have access to your camera or microphone. To fix this, open System Preferences.",primaryButtonText:"Try again",linkText:"Need help? Get troubleshooting help"};var BrowserPermissionDeniedIOS$d={primaryText:"Allow microphone access to continue",secondaryText:"So other participants can hear you.",primaryButtonText:"Try again",imageAltText:"Microphone and camera device permission location for iOS",linkText:"Need help? Get troubleshooting help",step1Text:"Go to the Settings app",step2Text:"Scroll down to settings for this browser",step3Text:"Turn on Microphone (Camera optional)",step4Text:"Try joining the call again",step1DigitText:"1",step2DigitText:"2",step3DigitText:"3",step4DigitText:"4"};var en_US$1 = {participantItem:participantItem$d,typingIndicator:typingIndicator$d,sendBox:sendBox$d,messageStatusIndicator:messageStatusIndicator$d,endCallButton:endCallButton$d,cameraButton:cameraButton$d,microphoneButton:microphoneButton$d,devicesButton:devicesButton$d,participantsButton:participantsButton$d,screenShareButton:screenShareButton$d,messageThread:messageThread$d,errorBar:errorBar$d,videoGallery:videoGallery$d,dialpad:dialpad$d,holdButton:holdButton$d,videoTile:videoTile$d,CameraAndMicrophoneDomainPermissionsRequest:CameraAndMicrophoneDomainPermissionsRequest,CameraDomainPermissionsRequest:CameraDomainPermissionsRequest,MicrophoneDomainPermissionsRequest:MicrophoneDomainPermissionsRequest,CameraAndMicrophoneDomainPermissionsCheck:CameraAndMicrophoneDomainPermissionsCheck,CameraDomainPermissionsCheck:CameraDomainPermissionsCheck,MicrophoneDomainPermissionsCheck:MicrophoneDomainPermissionsCheck,CameraAndMicrophoneDomainPermissionsDenied:CameraAndMicrophoneDomainPermissionsDenied,CameraDomainPermissionsDenied:CameraDomainPermissionsDenied,MicrophoneDomainPermissionsDenied:MicrophoneDomainPermissionsDenied,UnsupportedBrowser:UnsupportedBrowser$e,UnsupportedBrowserVersion:UnsupportedBrowserVersion$1,UnsupportedOperatingSystem:UnsupportedOperatingSystem$1,BrowserPermissionDenied:BrowserPermissionDenied$d,BrowserPermissionDeniedIOS:BrowserPermissionDeniedIOS$d};
4013
+ var participantItem$d={isMeText:"(you)",menuTitle:"More Options",removeButtonLabel:"Remove",sharingIconLabel:"Sharing",mutedIconLabel:"Muted",displayNamePlaceholder:"Unnamed participant",participantStateConnecting:"Calling...",participantStateRinging:"Calling...",participantStateHold:"On hold"};var typingIndicator$d={singleUser:"{user} is typing ...",multipleUsers:"{users} are typing ...",multipleUsersAbbreviateOne:"{users} and 1 other are typing ...",multipleUsersAbbreviateMany:"{users} and {numOthers} others are typing ...",delimiter:", "};var sendBox$d={placeholderText:"Enter a message",textTooLong:"Your message length is over the maximum limit.",sendButtonAriaLabel:"Send message",fileUploadsPendingError:"Uploading... Please wait.",removeFile:"Remove file",uploading:"Uploading",uploadCompleted:"Upload completed"};var messageStatusIndicator$d={deliveredAriaLabel:"Message sent",deliveredTooltipText:"Sent",seenAriaLabel:"Message seen by others",seenTooltipText:"Seen",readByTooltipText:"Read by {messageThreadReadCount} of {remoteParticipantsCount}",sendingAriaLabel:"Message sending",sendingTooltipText:"Sending",failedToSendAriaLabel:"Message failed to send",failedToSendTooltipText:"Failed to send"};var endCallButton$d={label:"Leave",tooltipContent:"Leave call"};var cameraButton$d={onLabel:"Turn off",offLabel:"Turn on",tooltipDisabledContent:"Camera is disabled",tooltipOnContent:"Turn off camera",tooltipOffContent:"Turn on camera",tooltipVideoLoadingContent:"Video is loading",cameraMenuTitle:"Camera",cameraMenuTooltip:"Choose camera",cameraButtonSplitRoleDescription:"Split button",onSplitButtonAriaLabel:"Turn off camera and camera options",offSplitButtonAriaLabel:"Turn on camera and camera options",cameraActionTurnedOnAnnouncement:"Your camera has been turned on",cameraActionTurnedOffAnnouncement:"Your camera has been turned off"};var microphoneButton$d={onLabel:"Mute",offLabel:"Unmute",tooltipDisabledContent:"Microphone is disabled",tooltipOnContent:"Mute microphone",tooltipOffContent:"Unmute microphone",microphoneMenuTitle:"Microphone",microphoneMenuTooltip:"Choose microphone",speakerMenuTitle:"Speaker",speakerMenuTooltip:"Choose speaker",microphoneButtonSplitRoleDescription:"Split button",onSplitButtonAriaLabel:"Mute microphone and audio options",offSplitButtonAriaLabel:"Unmute microphone and audio options",microphoneActionTurnedOnAnnouncement:"Your microphone has been turned on",microphoneActionTurnedOffAnnouncement:"Your microphone has been turned off"};var devicesButton$d={label:"Devices",tooltipContent:"Manage devices",cameraMenuTitle:"Camera",cameraMenuTooltip:"Choose camera",audioDeviceMenuTitle:"Audio Device",audioDeviceMenuTooltip:"Choose audio device",microphoneMenuTitle:"Microphone",microphoneMenuTooltip:"Choose microphone",speakerMenuTitle:"Speaker",speakerMenuTooltip:"Choose speaker"};var participantsButton$d={label:"People",tooltipContent:"Show participants",menuHeader:"In this call",participantsListButtonLabel:"{numParticipants} people",muteAllButtonLabel:"Mute all",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied"};var screenShareButton$d={onLabel:"Stop presenting",offLabel:"Present",tooltipDisabledContent:"Presenting is disabled",tooltipOnContent:"Presenting your screen",tooltipOffContent:"Present your screen"};var messageThread$d={yesterday:"Yesterday",sunday:"Sunday",monday:"Monday",tuesday:"Tuesday",wednesday:"Wednesday",thursday:"Thursday",friday:"Friday",saturday:"Saturday",participantJoined:"joined the chat.",participantLeft:"left the chat.",editMessage:"Edit",removeMessage:"Delete",resendMessage:"Try sending again",failToSendTag:"Failed to send",editedTag:"Edited",liveAuthorIntro:"{author} says",messageContentAriaText:"{author} said {message}",messageContentMineAriaText:"You said {message}",editBoxTextLimit:"Your message is over the limit of {limitNumber} characters",editBoxPlaceholderText:"Edit your message",newMessagesIndicator:"New messages",noDisplayNameSub:"No name",editBoxCancelButton:"Cancel",editBoxSubmitButton:"Submit",messageReadCount:"Read by {messageReadByCount} of {remoteParticipantsCount}",actionMenuMoreOptions:"More Options",downloadFile:"Download file"};var errorBar$d={unableToReachChatService:"You are offline",accessDenied:"Unable to access chat services - please check the user credentials provided",userNotInChatThread:"You are no longer in this chat thread",sendMessageNotInChatThread:"Failed to send message because you are no longer in this chat thread",sendMessageGeneric:"Failed to send message",callingNetworkFailure:"Troubling connecting call - you seem to be offline",startVideoGeneric:"Failed to start video",stopVideoGeneric:"Failed to stop video",muteGeneric:"Failed to mute microphone",unmuteGeneric:"Failed to unmute microphone",speakingWhileMuted:"Your microphone is muted",startScreenShareGeneric:"Failed to start screen sharing",stopScreenShareGeneric:"Failed to stop screen sharing",callNetworkQualityLow:"Network quality is low.",callNoSpeakerFound:"No speakers or headphones found. Connect an audio device to hear the call.",callNoMicrophoneFound:"No microphones found. Connect an audio input device.",callMicrophoneAccessDenied:"Unable to access microphone. Click the lock in the address bar to grant permission to this webpage.",callMicrophoneAccessDeniedSafari:"Unable to access microphone. Refresh the page to allow permissions, or check this browser’s settings and verify permissions are enabled for this website.",callMicrophoneMutedBySystem:"You are muted by your system.",callMicrophoneUnmutedBySystem:"Your microphone recovered and you were unmuted by your system.",callMacOsMicrophoneAccessDenied:"Unable to access microphone. Grant microphone permission in your macOS privacy settings.",callLocalVideoFreeze:"Network bandwidth is poor. Your video may appear paused for others on the call.",callCameraAccessDenied:"Unable to access camera. Click the lock in the address bar to grant permission to this webpage.",callCameraAccessDeniedSafari:"Unable to access camera. Refresh the page to allow permissions, or check this browser’s settings and verify permissions are enabled for this website.",callCameraAlreadyInUse:"Unable to access camera. It may already be in use by another application.",callVideoStoppedBySystem:"Your video has been stopped by your system.",callVideoRecoveredBySystem:"Your video has resumed.",callMacOsCameraAccessDenied:"MacOS is blocking access to your camera. Update your privacy settings to allow this browser to access your camera.",callMacOsScreenShareAccessDenied:"MacOS is blocking screen sharing. Update your privacy settings to allow this browser to record your screen.",dismissButtonAriaLabel:"Close",failedToJoinCallGeneric:"Failed to join call.",failedToJoinCallInvalidMeetingLink:"Unable to join Meeting. Invalid Link."};var videoGallery$d={screenIsBeingSharedMessage:"You are sharing your screen",screenShareLoadingMessage:"Loading {participant}'s screen",localVideoLabel:"You",localVideoCameraSwitcherLabel:"Switch camera",localVideoMovementLabel:"Movable Local Video Tile",localVideoSelectedDescription:"{cameraName} selected",displayNamePlaceholder:"Unnamed participant",fitRemoteParticipantToFrame:"Fit to frame",fillRemoteParticipantFrame:"Fill frame"};var dialpad$d={placeholderText:"Enter phone number",deleteButtonAriaLabel:"Delete"};var holdButton$d={onLabel:"Resume",offLabel:"Hold",tooltipOnContent:"Resume call",tooltipOffContent:"Hold call"};var videoTile$d={participantStateConnecting:"Calling...",participantStateRinging:"Calling...",participantStateHold:"On hold"};var CameraAndMicrophoneDomainPermissionsRequest={primaryText:"Allow {appName} to use your camera and microphone",secondaryText:"This is so participants can see and hear you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without camera and microphone",ariaLabel:"Allow camera and microphone access"};var CameraDomainPermissionsRequest={primaryText:"Allow {appName} to use your camera",secondaryText:"This is so participants can see you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without camera",ariaLabel:"Allow camera access"};var MicrophoneDomainPermissionsRequest={primaryText:"Allow {appName} to use your microphone",secondaryText:"This is so participants can hear you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without microphone",ariaLabel:"Allow microphone access"};var CameraAndMicrophoneDomainPermissionsCheck={primaryText:"Checking for camera and microphone access",secondaryText:"Allow access if prompted. This is so participants can see and hear you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without camera and microphone",ariaLabel:"Checking for camera and microphone access. Allow access if prompted."};var CameraDomainPermissionsCheck={primaryText:"Checking for camera access",secondaryText:"Allow access if prompted. This is so participants can see you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without camera",ariaLabel:"Checking for camera access. Allow access if prompted."};var MicrophoneDomainPermissionsCheck={primaryText:"Checking for microphone access",secondaryText:"Allow access if prompted. This is so participants can hear you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Continue without microphone",ariaLabel:"Checking for microphone access. Allow access if prompted."};var CameraAndMicrophoneDomainPermissionsDenied={primaryText:"Unable to access camera and microphone",secondaryText:"Click the lock icon in the address bar to grant microphone permissions to this webpage. A page refresh may be required.",primaryButtonText:"Continue without camera and microphone",linkText:"Need help? Get troubleshooting help"};var CameraAndMicrophoneDomainPermissionsDeniedSafari={primaryText:"Unable to access camera and microphone",secondaryText:"Refresh the page to allow permissions, or check this browser’s settings and verify permissions are enabled for this website.",primaryButtonText:"Continue without camera and microphone",linkText:"Need help? Get troubleshooting help"};var CameraDomainPermissionsDenied={primaryText:"Unable to access camera",secondaryText:"Click the lock icon in the address bar to grant camera permissions to this webpage. A page refresh may be required.",primaryButtonText:"Continue without camera",linkText:"Need help? Get troubleshooting help"};var MicrophoneDomainPermissionsDenied={primaryText:"Unable to access microphone",secondaryText:"Click the lock icon in the address bar to grant microphone permissions to this webpage. A page refresh may be required.",primaryButtonText:"Continue without microphone",linkText:"Need help? Get troubleshooting help"};var CameraDomainPermissionsDeniedSafari={primaryText:"Unable to access camera",secondaryText:"Refresh the page to allow permissions, or check this browser’s settings and verify permissions are enabled for this website.",primaryButtonText:"Continue without camera",linkText:"Need help? Get troubleshooting help"};var MicrophoneDomainPermissionsDeniedSafari={primaryText:"Unable to access microphone",secondaryText:"Refresh the page to allow permissions, or check this browser’s settings and verify permissions are enabled for this website.",primaryButtonText:"Continue without microphone",linkText:"Need help? Get troubleshooting help"};var UnsupportedBrowser$e={primaryText:"Browser not supported",secondaryText:"Please join this call using a compatible browser.",moreHelpLinkText:"See compatibility requirements"};var UnsupportedBrowserVersion$1={primaryText:"Browser update needed",secondaryText:"To ensure the best call possible, please update your browser and then try joining the call again.",moreHelpLinkText:"See compatibility requirements",continueAnywayButtonText:"Start call without updating"};var UnsupportedOperatingSystem$1={primaryText:"Operating system not supported",secondaryText:"Please join this call using a device with a compatible operating system.",moreHelpLinkText:"See compatibility requirements"};var BrowserPermissionDenied$d={primaryText:"Can't use your camera or microphone",secondaryText:"Your browser might not have access to your camera or microphone. To fix this, open System Preferences.",primaryButtonText:"Try again",linkText:"Need help? Get troubleshooting help"};var BrowserPermissionDeniedIOS$d={primaryText:"Allow microphone access to continue",secondaryText:"So other participants can hear you.",primaryButtonText:"Try again",imageAltText:"Microphone and camera device permission location for iOS",linkText:"Need help? Get troubleshooting help",step1Text:"Go to the Settings app",step2Text:"Scroll down to settings for this browser",step3Text:"Turn on Microphone (Camera optional)",step4Text:"Try joining the call again",step1DigitText:"1",step2DigitText:"2",step3DigitText:"3",step4DigitText:"4"};var en_US$1 = {participantItem:participantItem$d,typingIndicator:typingIndicator$d,sendBox:sendBox$d,messageStatusIndicator:messageStatusIndicator$d,endCallButton:endCallButton$d,cameraButton:cameraButton$d,microphoneButton:microphoneButton$d,devicesButton:devicesButton$d,participantsButton:participantsButton$d,screenShareButton:screenShareButton$d,messageThread:messageThread$d,errorBar:errorBar$d,videoGallery:videoGallery$d,dialpad:dialpad$d,holdButton:holdButton$d,videoTile:videoTile$d,CameraAndMicrophoneDomainPermissionsRequest:CameraAndMicrophoneDomainPermissionsRequest,CameraDomainPermissionsRequest:CameraDomainPermissionsRequest,MicrophoneDomainPermissionsRequest:MicrophoneDomainPermissionsRequest,CameraAndMicrophoneDomainPermissionsCheck:CameraAndMicrophoneDomainPermissionsCheck,CameraDomainPermissionsCheck:CameraDomainPermissionsCheck,MicrophoneDomainPermissionsCheck:MicrophoneDomainPermissionsCheck,CameraAndMicrophoneDomainPermissionsDenied:CameraAndMicrophoneDomainPermissionsDenied,CameraAndMicrophoneDomainPermissionsDeniedSafari:CameraAndMicrophoneDomainPermissionsDeniedSafari,CameraDomainPermissionsDenied:CameraDomainPermissionsDenied,MicrophoneDomainPermissionsDenied:MicrophoneDomainPermissionsDenied,CameraDomainPermissionsDeniedSafari:CameraDomainPermissionsDeniedSafari,MicrophoneDomainPermissionsDeniedSafari:MicrophoneDomainPermissionsDeniedSafari,UnsupportedBrowser:UnsupportedBrowser$e,UnsupportedBrowserVersion:UnsupportedBrowserVersion$1,UnsupportedOperatingSystem:UnsupportedOperatingSystem$1,BrowserPermissionDenied:BrowserPermissionDenied$d,BrowserPermissionDeniedIOS:BrowserPermissionDeniedIOS$d};
4007
4014
 
4008
4015
  var participantItem$c={isMeText:"(you)",menuTitle:"More Options",removeButtonLabel:"Remove",sharingIconLabel:"Sharing",mutedIconLabel:"Muted",displayNamePlaceholder:"Unnamed participant",participantStateConnecting:"Calling...",participantStateRinging:"Calling...",participantStateHold:"On hold"};var typingIndicator$c={singleUser:"{user} is typing ...",multipleUsers:"{users} are typing ...",multipleUsersAbbreviateOne:"{users} and 1 other are typing ...",multipleUsersAbbreviateMany:"{users} and {numOthers} others are typing ...",delimiter:", "};var sendBox$c={placeholderText:"Enter a message",textTooLong:"Your message length is over the maximum limit.",sendButtonAriaLabel:"Send message",fileUploadsPendingError:"Uploading... Please wait.",removeFile:"Remove file",uploading:"Uploading",uploadCompleted:"Upload completed"};var messageStatusIndicator$c={deliveredAriaLabel:"Message sent",deliveredTooltipText:"Sent",seenAriaLabel:"Message seen by others",seenTooltipText:"Seen",readByTooltipText:"Read by {messageThreadReadCount} of {remoteParticipantsCount}",sendingAriaLabel:"Message sending",sendingTooltipText:"Sending",failedToSendAriaLabel:"Message failed to send",failedToSendTooltipText:"Failed to send"};var endCallButton$c={label:"Leave",tooltipContent:"Leave call"};var cameraButton$c={onLabel:"Turn off",offLabel:"Turn on",tooltipDisabledContent:"Camera is disabled",tooltipOnContent:"Turn off camera",tooltipOffContent:"Turn on camera",tooltipVideoLoadingContent:"Video is loading",cameraMenuTitle:"Camera",cameraMenuTooltip:"Choose camera",cameraButtonSplitRoleDescription:"Split button",onSplitButtonAriaLabel:"Turn off camera and camera options",offSplitButtonAriaLabel:"Turn on camera and camera options",cameraActionTurnedOnAnnouncement:"Your camera has been turned on",cameraActionTurnedOffAnnouncement:"Your camera has been turned off"};var microphoneButton$c={onLabel:"Mute",offLabel:"Unmute",tooltipDisabledContent:"Microphone is disabled",tooltipOnContent:"Mute microphone",tooltipOffContent:"Unmute microphone",microphoneMenuTitle:"Microphone",microphoneMenuTooltip:"Choose microphone",speakerMenuTitle:"Speaker",speakerMenuTooltip:"Choose speaker",microphoneButtonSplitRoleDescription:"Split button",onSplitButtonAriaLabel:"Mute microphone and audio options",offSplitButtonAriaLabel:"Unmute microphone and audio options",microphoneActionTurnedOnAnnouncement:"Your microphone has been turned on",microphoneActionTurnedOffAnnouncement:"Your microphone has been turned off"};var devicesButton$c={label:"Devices",tooltipContent:"Manage devices",cameraMenuTitle:"Camera",cameraMenuTooltip:"Choose camera",audioDeviceMenuTitle:"Audio Device",audioDeviceMenuTooltip:"Choose audio device",microphoneMenuTitle:"Microphone",microphoneMenuTooltip:"Choose microphone",speakerMenuTitle:"Speaker",speakerMenuTooltip:"Choose speaker"};var participantsButton$c={label:"People",tooltipContent:"Show participants",menuHeader:"In this call",participantsListButtonLabel:"{numParticipants} people",muteAllButtonLabel:"Mute all",copyInviteLinkButtonLabel:"Copy invite link"};var screenShareButton$c={onLabel:"Stop presenting",offLabel:"Present",tooltipDisabledContent:"Presenting is disabled",tooltipOnContent:"Presenting your screen",tooltipOffContent:"Present your screen"};var messageThread$c={yesterday:"Yesterday",sunday:"Sunday",monday:"Monday",tuesday:"Tuesday",wednesday:"Wednesday",thursday:"Thursday",friday:"Friday",saturday:"Saturday",participantJoined:"joined the chat.",participantLeft:"left the chat.",editMessage:"Edit",removeMessage:"Delete",resendMessage:"Try sending again",failToSendTag:"Failed to send",editedTag:"Edited",liveAuthorIntro:"{author} says",messageContentAriaText:"{author} said {message}",messageContentMineAriaText:"You said {message}",editBoxTextLimit:"Your message is over the limit of {limitNumber} characters",editBoxPlaceholderText:"Edit your message",newMessagesIndicator:"New messages",noDisplayNameSub:"No name",editBoxCancelButton:"Cancel",editBoxSubmitButton:"Submit",messageReadCount:"Read by {messageReadByCount} of {remoteParticipantsCount}",actionMenuMoreOptions:"More Options",downloadFile:"Download file"};var errorBar$c={unableToReachChatService:"You are offline",accessDenied:"Unable to access chat services - please check the user credentials provided",userNotInChatThread:"You are no longer in this chat thread",sendMessageNotInChatThread:"Failed to send message because you are no longer in this chat thread",sendMessageGeneric:"Failed to send message",callingNetworkFailure:"Troubling connecting call - you seem to be offline",startVideoGeneric:"Failed to start video",stopVideoGeneric:"Failed to stop video",muteGeneric:"Failed to mute microphone",unmuteGeneric:"Failed to unmute microphone",speakingWhileMuted:"Your microphone is muted",startScreenShareGeneric:"Failed to start screen sharing",stopScreenShareGeneric:"Failed to stop screen sharing",callNetworkQualityLow:"Network quality is low.",callNoSpeakerFound:"No speakers or headphones found. Connect an audio device to hear the call.",callNoMicrophoneFound:"No microphones found. Connect an audio input device.",callMicrophoneAccessDenied:"Unable to access microphone. Click the lock in the address bar to grant permission to this webpage.",callMicrophoneMutedBySystem:"You are muted by your system.",callMicrophoneUnmutedBySystem:"Your microphone recovered and you were unmuted by your system.",callMacOsMicrophoneAccessDenied:"Unable to access microphone. Grant microphone permission in your macOS privacy settings.",callLocalVideoFreeze:"Network bandwidth is poor. Your video may appear paused for others on the call.",callCameraAccessDenied:"Unable to access camera. Click the lock in the address bar to grant permission to this webpage.",callCameraAlreadyInUse:"Unable to access camera. It may already be in use by another application.",callVideoStoppedBySystem:"Your video has been stopped by your system.",callVideoRecoveredBySystem:"Your video has resumed.",callMacOsCameraAccessDenied:"MacOS is blocking access to your camera. Update your privacy settings to allow this browser to access your camera.",callMacOsScreenShareAccessDenied:"MacOS is blocking screen sharing. Update your privacy settings to allow this browser to record your screen.",dismissButtonAriaLabel:"Close",failedToJoinCallGeneric:"Failed to join call.",failedToJoinCallInvalidMeetingLink:"Unable to join Meeting. Invalid Link."};var videoGallery$c={screenIsBeingSharedMessage:"You are sharing your screen",screenShareLoadingMessage:"Loading {participant}'s screen",localVideoLabel:"You",localVideoCameraSwitcherLabel:"Switch camera",localVideoMovementLabel:"Movable Local Video Tile",localVideoSelectedDescription:"{cameraName} selected",displayNamePlaceholder:"Unnamed participant"};var dialpad$c={placeholderText:"Enter phone number",deleteButtonAriaLabel:"Delete"};var holdButton$c={onLabel:"Resume",offLabel:"Hold",tooltipOnContent:"Resume call",tooltipOffContent:"Hold call"};var videoTile$c={participantStateConnecting:"Calling...",participantStateRinging:"Calling...",participantStateHold:"On hold"};var DomainPermissions$c={primaryText:"Allow {appName} to use your camera and microphone",secondaryText:"This is so participants can see and hear you.",linkText:"Need help? Get troubleshooting help",primaryButtonText:"Allow Access"};var UnsupportedBrowser$d={primaryText:"Browser not supported",secondaryText:"Please join this call using a compatible browser.",moreHelpLink:"More help"};var BrowserPermissionDenied$c={primaryText:"Can't use your camera or microphone",secondaryText:"Your browser might not have access to your camera or microphone. To fix this, open System Preferences.",primaryButtonText:"Try again",linkText:"Need help? Get troubleshooting help"};var BrowserPermissionDeniedIOS$c={primaryText:"Allow microphone access to continue",secondaryText:"So other participants can hear you.",primaryButtonText:"Try again",imageAltText:"Microphone and camera device permission location for iOS",linkText:"Need help? Get troubleshooting help",step1Text:"Go to the Settings app",step2Text:"Scroll down to settings for this browser",step3Text:"Turn on Microphone (Camera optional)",step4Text:"Try joining the call again",step1DigitText:"1",step2DigitText:"2",step3DigitText:"3",step4DigitText:"4"};var en_GB$1 = {participantItem:participantItem$c,typingIndicator:typingIndicator$c,sendBox:sendBox$c,messageStatusIndicator:messageStatusIndicator$c,endCallButton:endCallButton$c,cameraButton:cameraButton$c,microphoneButton:microphoneButton$c,devicesButton:devicesButton$c,participantsButton:participantsButton$c,screenShareButton:screenShareButton$c,messageThread:messageThread$c,errorBar:errorBar$c,videoGallery:videoGallery$c,dialpad:dialpad$c,holdButton:holdButton$c,videoTile:videoTile$c,DomainPermissions:DomainPermissions$c,UnsupportedBrowser:UnsupportedBrowser$d,BrowserPermissionDenied:BrowserPermissionDenied$c,BrowserPermissionDeniedIOS:BrowserPermissionDeniedIOS$c};
4009
4016
 
@@ -4454,11 +4461,13 @@ const messageBarType = (errorType) => {
4454
4461
  case 'callNoSpeakerFound':
4455
4462
  case 'callNoMicrophoneFound':
4456
4463
  case 'callMicrophoneAccessDenied':
4464
+ case 'callMicrophoneAccessDeniedSafari':
4457
4465
  case 'callMicrophoneMutedBySystem':
4458
4466
  case 'callMicrophoneUnmutedBySystem':
4459
4467
  case 'callMacOsMicrophoneAccessDenied':
4460
4468
  case 'callLocalVideoFreeze':
4461
4469
  case 'callCameraAccessDenied':
4470
+ case 'callCameraAccessDeniedSafari':
4462
4471
  case 'callCameraAlreadyInUse':
4463
4472
  case 'callVideoStoppedBySystem':
4464
4473
  case 'callVideoRecoveredBySystem':
@@ -4486,11 +4495,13 @@ const customIconName = {
4486
4495
  callNoSpeakerFound: 'ErrorBarCallNoSpeakerFound',
4487
4496
  callNoMicrophoneFound: 'ErrorBarCallNoMicrophoneFound',
4488
4497
  callMicrophoneAccessDenied: 'ErrorBarCallMicrophoneAccessDenied',
4498
+ callMicrophoneAccessDeniedSafari: 'ErrorBarCallMicrophoneAccessDenied',
4489
4499
  callMicrophoneMutedBySystem: 'ErrorBarCallMicrophoneMutedBySystem',
4490
4500
  callMicrophoneUnmutedBySystem: 'ErrorBarCallMicrophoneUnmutedBySystem',
4491
4501
  callMacOsMicrophoneAccessDenied: 'ErrorBarCallMacOsMicrophoneAccessDenied',
4492
4502
  callLocalVideoFreeze: 'ErrorBarCallLocalVideoFreeze',
4493
4503
  callCameraAccessDenied: 'ErrorBarCallCameraAccessDenied',
4504
+ callCameraAccessDeniedSafari: 'ErrorBarCallCameraAccessDenied',
4494
4505
  callCameraAlreadyInUse: 'ErrorBarCallCameraAlreadyInUse',
4495
4506
  callVideoStoppedBySystem: 'ErrorBarCallVideoStoppedBySystem',
4496
4507
  callVideoRecoveredBySystem: 'ErrorBarCallVideoRecoveredBySystem',
@@ -10708,7 +10719,9 @@ const CameraAndMicrophoneDomainPermissions = (props) => {
10708
10719
  const locale = useLocale$1().strings;
10709
10720
  /* @conditional-compile-remove(call-readiness) */
10710
10721
  const strings = useShallowMerge(props.type === 'denied'
10711
- ? locale.CameraAndMicrophoneDomainPermissionsDenied
10722
+ ? props.browserHint === 'safari'
10723
+ ? locale.CameraAndMicrophoneDomainPermissionsDeniedSafari
10724
+ : locale.CameraAndMicrophoneDomainPermissionsDenied
10712
10725
  : props.type === 'request'
10713
10726
  ? locale.CameraAndMicrophoneDomainPermissionsRequest
10714
10727
  : locale.CameraAndMicrophoneDomainPermissionsCheck, props.strings);
@@ -10733,7 +10746,9 @@ const MicrophoneDomainPermissions = (props) => {
10733
10746
  const locale = useLocale$1().strings;
10734
10747
  /* @conditional-compile-remove(call-readiness) */
10735
10748
  const strings = useShallowMerge(props.type === 'denied'
10736
- ? locale.MicrophoneDomainPermissionsDenied
10749
+ ? props.browserHint === 'safari'
10750
+ ? locale.MicrophoneDomainPermissionsDeniedSafari
10751
+ : locale.MicrophoneDomainPermissionsDenied
10737
10752
  : props.type === 'request'
10738
10753
  ? locale.MicrophoneDomainPermissionsRequest
10739
10754
  : locale.MicrophoneDomainPermissionsCheck, props.strings);
@@ -10754,7 +10769,9 @@ const CameraDomainPermissions = (props) => {
10754
10769
  const locale = useLocale$1().strings;
10755
10770
  /* @conditional-compile-remove(call-readiness) */
10756
10771
  const strings = useShallowMerge(props.type === 'denied'
10757
- ? locale.CameraDomainPermissionsDenied
10772
+ ? props.browserHint === 'safari'
10773
+ ? locale.CameraDomainPermissionsDeniedSafari
10774
+ : locale.CameraDomainPermissionsDenied
10758
10775
  : props.type === 'request'
10759
10776
  ? locale.CameraDomainPermissionsRequest
10760
10777
  : locale.CameraDomainPermissionsCheck, props.strings);
@@ -10780,6 +10797,7 @@ const ParticipantsButton = (props) => {
10780
10797
  var _a, _b, _c, _d;
10781
10798
  const { callInvitationURL, styles, onMuteAll, onRenderIcon, onRenderParticipantList, participants, myUserId, excludeMe, onRenderParticipant, onRenderAvatar, onRemoveParticipant, onFetchParticipantMenuItems, showParticipantOverflowTooltip } = props;
10782
10799
  const disabled = props.disabled;
10800
+ const [copyInviteLinkAnnouncerStrings, setCopyInviteLinkAnnouncerStrings] = React.useState('');
10783
10801
  const onRenderPeopleIcon = () => (React__default['default'].createElement(_HighContrastAwareIcon, { disabled: disabled, iconName: "ControlButtonParticipants" }));
10784
10802
  const ids = useIdentifiers();
10785
10803
  const onMuteAllCallback = React.useCallback(() => {
@@ -10810,6 +10828,19 @@ const ParticipantsButton = (props) => {
10810
10828
  const localeStrings = useLocale$1().strings.participantsButton;
10811
10829
  const strings = React.useMemo(() => (Object.assign(Object.assign({}, localeStrings), props.strings)), [localeStrings, props.strings]);
10812
10830
  const participantCount = participants.length;
10831
+ /**
10832
+ * sets the announcement string for when the link is copied.
10833
+ */
10834
+ const toggleAnnouncerString = React.useCallback(() => {
10835
+ setCopyInviteLinkAnnouncerStrings(strings.copyInviteLinkActionedAriaLabel);
10836
+ /**
10837
+ * Clears the announcer string after the user clicks the
10838
+ * copyInviteLink button allowing it to be re-announced.
10839
+ */
10840
+ setTimeout(() => {
10841
+ setCopyInviteLinkAnnouncerStrings('');
10842
+ }, 3000);
10843
+ }, [strings.copyInviteLinkActionedAriaLabel]);
10813
10844
  const generateDefaultParticipantsSubMenuProps = React.useCallback(() => {
10814
10845
  var _a;
10815
10846
  const items = [];
@@ -10889,7 +10920,10 @@ const ParticipantsButton = (props) => {
10889
10920
  title: strings.copyInviteLinkButtonLabel,
10890
10921
  itemProps: { styles: (_b = styles === null || styles === void 0 ? void 0 : styles.menuStyles) === null || _b === void 0 ? void 0 : _b.menuItemStyles },
10891
10922
  iconProps: { iconName: 'Link' },
10892
- onClick: onCopyCallback
10923
+ onClick: () => {
10924
+ onCopyCallback();
10925
+ toggleAnnouncerString();
10926
+ }
10893
10927
  });
10894
10928
  }
10895
10929
  return menuProps;
@@ -10904,9 +10938,12 @@ const ParticipantsButton = (props) => {
10904
10938
  excludeMe,
10905
10939
  ids.participantButtonPeopleMenuItem,
10906
10940
  generateDefaultParticipantsSubMenuProps,
10907
- onCopyCallback
10941
+ onCopyCallback,
10942
+ toggleAnnouncerString
10908
10943
  ]);
10909
- return (React__default['default'].createElement(ControlBarButton, Object.assign({}, props, { disabled: disabled, menuProps: (_c = props.menuProps) !== null && _c !== void 0 ? _c : defaultMenuProps, menuIconProps: { hidden: true }, onRenderIcon: onRenderIcon !== null && onRenderIcon !== void 0 ? onRenderIcon : onRenderPeopleIcon, strings: strings, labelKey: (_d = props.labelKey) !== null && _d !== void 0 ? _d : 'participantsButtonLabel' })));
10944
+ return (React__default['default'].createElement(React__default['default'].Fragment, null,
10945
+ React__default['default'].createElement(Announcer, { announcementString: copyInviteLinkAnnouncerStrings, ariaLive: 'polite' }),
10946
+ React__default['default'].createElement(ControlBarButton, Object.assign({}, props, { disabled: disabled, menuProps: (_c = props.menuProps) !== null && _c !== void 0 ? _c : defaultMenuProps, menuIconProps: { hidden: true }, onRenderIcon: onRenderIcon !== null && onRenderIcon !== void 0 ? onRenderIcon : onRenderPeopleIcon, strings: strings, labelKey: (_d = props.labelKey) !== null && _d !== void 0 ? _d : 'participantsButtonLabel' }))));
10910
10947
  };
10911
10948
 
10912
10949
  // Copyright (c) Microsoft Corporation.
@@ -12324,8 +12361,8 @@ const useSelector$4 = (selector, selectorProps) => {
12324
12361
  *
12325
12362
  * @public
12326
12363
  */
12327
- const errorBarSelector$1 = reselect.createSelector([getLatestErrors$1, getDiagnostics, getDeviceManager$1], (latestErrors, diagnostics, deviceManager) => {
12328
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
12364
+ const errorBarSelector$1 = reselect.createSelector([getLatestErrors$1, getDiagnostics, getDeviceManager$1, getEnvironmentInfo], (latestErrors, diagnostics, deviceManager, environmentInfo) => {
12365
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
12329
12366
  // The order in which the errors are returned is significant: The `ErrorBar` shows errors on the UI in that order.
12330
12367
  // There are several options for the ordering:
12331
12368
  // - Sorted by when the errors happened (latest first / oldest first).
@@ -12334,6 +12371,10 @@ const errorBarSelector$1 = reselect.createSelector([getLatestErrors$1, getDiagno
12334
12371
  // We chose to stable sort by error type: We intend to show only a small number of errors on the UI and we do not
12335
12372
  // have timestamps for errors.
12336
12373
  const activeErrorMessages = [];
12374
+ const isSafari = () => {
12375
+ /* @conditional-compile-remove(unsupported-browser) */
12376
+ return (environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.environment.browser) === 'safari';
12377
+ };
12337
12378
  // Errors reported via diagnostics are more reliable than from API method failures, so process those first.
12338
12379
  if (((_a = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.network.latest.networkReceiveQuality) === null || _a === void 0 ? void 0 : _a.value) === communicationCalling.DiagnosticQuality.Bad ||
12339
12380
  ((_b = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.network.latest.networkReceiveQuality) === null || _b === void 0 ? void 0 : _b.value) === communicationCalling.DiagnosticQuality.Poor) {
@@ -12345,10 +12386,13 @@ const errorBarSelector$1 = reselect.createSelector([getLatestErrors$1, getDiagno
12345
12386
  if (((_d = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.noMicrophoneDevicesEnumerated) === null || _d === void 0 ? void 0 : _d.value) === true) {
12346
12387
  activeErrorMessages.push({ type: 'callNoMicrophoneFound' });
12347
12388
  }
12348
- if (((_e = deviceManager.deviceAccess) === null || _e === void 0 ? void 0 : _e.audio) === false) {
12389
+ if (((_e = deviceManager.deviceAccess) === null || _e === void 0 ? void 0 : _e.audio) === false && isSafari()) {
12390
+ activeErrorMessages.push({ type: 'callMicrophoneAccessDeniedSafari' });
12391
+ }
12392
+ if (((_f = deviceManager.deviceAccess) === null || _f === void 0 ? void 0 : _f.audio) === false && !isSafari()) {
12349
12393
  activeErrorMessages.push({ type: 'callMicrophoneAccessDenied' });
12350
12394
  }
12351
- if (((_f = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.microphonePermissionDenied) === null || _f === void 0 ? void 0 : _f.value) === true) {
12395
+ if (((_g = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.microphonePermissionDenied) === null || _g === void 0 ? void 0 : _g.value) === true) {
12352
12396
  activeErrorMessages.push({ type: 'callMacOsMicrophoneAccessDenied' });
12353
12397
  }
12354
12398
  const microphoneMuteUnexpectedlyDiagnostic = (diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.microphoneMuteUnexpectedly) || (diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.microphoneNotFunctioning);
@@ -12373,18 +12417,21 @@ const errorBarSelector$1 = reselect.createSelector([getLatestErrors$1, getDiagno
12373
12417
  activeErrorMessages.push({ type: 'callVideoRecoveredBySystem' });
12374
12418
  }
12375
12419
  }
12376
- if (((_g = deviceManager.deviceAccess) === null || _g === void 0 ? void 0 : _g.video) === false) {
12420
+ if (((_h = deviceManager.deviceAccess) === null || _h === void 0 ? void 0 : _h.video) === false && isSafari()) {
12421
+ activeErrorMessages.push({ type: 'callCameraAccessDeniedSafari' });
12422
+ }
12423
+ else if (((_j = deviceManager.deviceAccess) === null || _j === void 0 ? void 0 : _j.video) === false) {
12377
12424
  activeErrorMessages.push({ type: 'callCameraAccessDenied' });
12378
12425
  }
12379
12426
  else {
12380
- if (((_h = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.cameraFreeze) === null || _h === void 0 ? void 0 : _h.value) === true) {
12427
+ if (((_k = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.cameraFreeze) === null || _k === void 0 ? void 0 : _k.value) === true) {
12381
12428
  activeErrorMessages.push({ type: 'callCameraAlreadyInUse' });
12382
12429
  }
12383
12430
  }
12384
- if (((_j = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.cameraPermissionDenied) === null || _j === void 0 ? void 0 : _j.value) === true) {
12431
+ if (((_l = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.cameraPermissionDenied) === null || _l === void 0 ? void 0 : _l.value) === true) {
12385
12432
  activeErrorMessages.push({ type: 'callMacOsCameraAccessDenied' });
12386
12433
  }
12387
- if (((_k = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.screenshareRecordingDisabled) === null || _k === void 0 ? void 0 : _k.value) === true) {
12434
+ if (((_m = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.screenshareRecordingDisabled) === null || _m === void 0 ? void 0 : _m.value) === true) {
12388
12435
  activeErrorMessages.push({ type: 'callMacOsScreenShareAccessDenied' });
12389
12436
  }
12390
12437
  // Prefer to show errors with privacy implications.
@@ -12393,7 +12440,7 @@ const errorBarSelector$1 = reselect.createSelector([getLatestErrors$1, getDiagno
12393
12440
  appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.stopScreenSharing', 'stopScreenShareGeneric');
12394
12441
  appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.startVideo', 'startVideoGeneric');
12395
12442
  appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.unmute', 'unmuteGeneric');
12396
- if (((_l = latestErrors['CallAgent.join']) === null || _l === void 0 ? void 0 : _l.message) === 'CallAgent.join: Invalid meeting link') {
12443
+ if (((_o = latestErrors['CallAgent.join']) === null || _o === void 0 ? void 0 : _o.message) === 'CallAgent.join: Invalid meeting link') {
12397
12444
  appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'CallAgent.join', 'failedToJoinCallInvalidMeetingLink');
12398
12445
  }
12399
12446
  else {
@@ -14749,182 +14796,464 @@ const convertObservableFileUploadToFileUploadsUiState = (fileUploads) => {
14749
14796
 
14750
14797
  // Copyright (c) Microsoft Corporation.
14751
14798
  // Licensed under the MIT license.
14752
- var __awaiter$c = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
14753
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14754
- return new (P || (P = Promise))(function (resolve, reject) {
14755
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
14756
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
14757
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
14758
- step((generator = generator.apply(thisArg, _arguments || [])).next());
14759
- });
14760
- };
14761
- var __asyncValues = (window && window.__asyncValues) || function (o) {
14762
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
14763
- var m = o[Symbol.asyncIterator], i;
14764
- return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
14765
- function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
14766
- function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
14767
- };
14768
14799
  /**
14769
- * Context of Chat, which is a centralized context for all state updates
14800
+ * Subset of CallCompositePages that represent an end call state.
14770
14801
  * @private
14771
14802
  */
14772
- class ChatContext {
14773
- constructor(clientState, threadId) {
14774
- this.emitter = new EventEmitter__default['default']();
14775
- const thread = clientState.threads[threadId];
14776
- this.threadId = threadId;
14777
- if (!thread) {
14778
- throw 'Cannot find threadId, please initialize thread before use!';
14779
- }
14780
- this.state = {
14781
- userId: clientState.userId,
14782
- displayName: clientState.displayName,
14783
- thread,
14784
- latestErrors: clientState.latestErrors
14785
- };
14786
- }
14787
- onStateChange(handler) {
14788
- this.emitter.on('stateChanged', handler);
14789
- }
14790
- offStateChange(handler) {
14791
- this.emitter.off('stateChanged', handler);
14792
- }
14793
- setState(state) {
14794
- this.state = state;
14795
- this.emitter.emit('stateChanged', this.state);
14796
- }
14797
- getState() {
14798
- return this.state;
14799
- }
14800
- setError(error) {
14801
- this.setState(Object.assign(Object.assign({}, this.state), { error }));
14803
+ const END_CALL_PAGES = [
14804
+ 'accessDeniedTeamsMeeting',
14805
+ 'joinCallFailedDueToNoNetwork',
14806
+ 'leftCall',
14807
+ /* @conditional-compile-remove(rooms) */ 'deniedPermissionToRoom',
14808
+ 'removedFromCall',
14809
+ /* @conditional-compile-remove(rooms) */ 'roomNotFound',
14810
+ /* @conditional-compile-remove(unsupported-browser) */ 'unsupportedEnvironment'
14811
+ ];
14812
+
14813
+ // Copyright (c) Microsoft Corporation.
14814
+ const ACCESS_DENIED_TEAMS_MEETING_SUB_CODE = 5854;
14815
+ const REMOTE_PSTN_USER_HUNG_UP = 560000;
14816
+ const REMOVED_FROM_CALL_SUB_CODES = [5000, 5300, REMOTE_PSTN_USER_HUNG_UP];
14817
+ /* @conditional-compile-remove(rooms) */
14818
+ const ROOM_NOT_FOUND_SUB_CODE = 5751;
14819
+ /* @conditional-compile-remove(rooms) */
14820
+ const DENIED_PERMISSION_TO_ROOM_SUB_CODE = 5828;
14821
+ /**
14822
+ * @private
14823
+ */
14824
+ const isCameraOn = (state) => {
14825
+ if (state.call) {
14826
+ const stream = state.call.localVideoStreams.find((stream) => stream.mediaStreamType === 'Video');
14827
+ return !!stream;
14802
14828
  }
14803
- updateClientState(clientState) {
14804
- const thread = clientState.threads[this.threadId];
14805
- if (!thread) {
14806
- throw 'Cannot find threadId, please make sure thread state is still in Stateful ChatClient.';
14829
+ else {
14830
+ if (state.devices.selectedCamera) {
14831
+ const previewOn = _isPreviewOn(state.devices);
14832
+ return previewOn;
14807
14833
  }
14808
- let updatedState = {
14809
- userId: clientState.userId,
14810
- displayName: clientState.displayName,
14811
- thread,
14812
- latestErrors: clientState.latestErrors
14813
- };
14814
- /* @conditional-compile-remove(file-sharing) */
14815
- updatedState = Object.assign(Object.assign({}, updatedState), { fileUploads: this.state.fileUploads });
14816
- this.setState(updatedState);
14817
14834
  }
14818
- }
14835
+ return false;
14836
+ };
14819
14837
  /**
14838
+ * Reduce the set of call controls visible on mobile.
14839
+ * For example do not show screenshare button.
14840
+ *
14820
14841
  * @private
14821
14842
  */
14822
- class AzureCommunicationChatAdapter {
14823
- constructor(chatClient, chatThreadClient) {
14824
- this.emitter = new EventEmitter__default['default']();
14825
- this.bindAllPublicMethods();
14826
- this.chatClient = chatClient;
14827
- this.chatThreadClient = chatThreadClient;
14828
- this.context = new ChatContext(chatClient.getState(), chatThreadClient.threadId);
14829
- /* @conditional-compile-remove(file-sharing) */
14830
- this.fileUploadAdapter = new AzureCommunicationFileUploadAdapter(this.context);
14831
- const onStateChange = (clientState) => {
14832
- // unsubscribe when the instance gets disposed
14833
- if (!this) {
14834
- chatClient.offStateChange(onStateChange);
14835
- return;
14836
- }
14837
- this.context.updateClientState(clientState);
14838
- };
14839
- this.handlers = createDefaultChatHandlers(chatClient, chatThreadClient);
14840
- this.chatClient.onStateChange(onStateChange);
14841
- this.subscribeAllEvents();
14843
+ const reduceCallControlsForMobile = (callControlOptions) => {
14844
+ if (callControlOptions === false) {
14845
+ return false;
14842
14846
  }
14843
- bindAllPublicMethods() {
14844
- this.onStateChange = this.onStateChange.bind(this);
14845
- this.offStateChange = this.offStateChange.bind(this);
14846
- this.getState = this.getState.bind(this);
14847
- this.dispose = this.dispose.bind(this);
14848
- this.fetchInitialData = this.fetchInitialData.bind(this);
14849
- this.sendMessage = this.sendMessage.bind(this);
14850
- this.sendReadReceipt = this.sendReadReceipt.bind(this);
14851
- this.sendTypingIndicator = this.sendTypingIndicator.bind(this);
14852
- this.updateMessage = this.updateMessage.bind(this);
14853
- this.deleteMessage = this.deleteMessage.bind(this);
14854
- this.removeParticipant = this.removeParticipant.bind(this);
14855
- this.setTopic = this.setTopic.bind(this);
14856
- this.loadPreviousChatMessages = this.loadPreviousChatMessages.bind(this);
14857
- this.on = this.on.bind(this);
14858
- this.off = this.off.bind(this);
14859
- /* @conditional-compile-remove(file-sharing) */
14860
- this.registerActiveFileUploads = this.registerActiveFileUploads.bind(this);
14861
- /* @conditional-compile-remove(file-sharing) */
14862
- this.registerCompletedFileUploads = this.registerCompletedFileUploads.bind(this);
14863
- /* @conditional-compile-remove(file-sharing) */
14864
- this.clearFileUploads = this.clearFileUploads.bind(this);
14865
- /* @conditional-compile-remove(file-sharing) */
14866
- this.cancelFileUpload = this.cancelFileUpload.bind(this);
14867
- /* @conditional-compile-remove(file-sharing) */
14868
- this.updateFileUploadProgress = this.updateFileUploadProgress.bind(this);
14869
- /* @conditional-compile-remove(file-sharing) */
14870
- this.updateFileUploadErrorMessage = this.updateFileUploadErrorMessage.bind(this);
14871
- /* @conditional-compile-remove(file-sharing) */
14872
- this.updateFileUploadMetadata = this.updateFileUploadMetadata.bind(this);
14847
+ // Ensure call controls a valid object.
14848
+ const reduceCallControlOptions = callControlOptions === true ? {} : callControlOptions || {};
14849
+ // Set to compressed mode when composite is optimized for mobile
14850
+ reduceCallControlOptions.displayType = 'compact';
14851
+ // Do not show screen share button when composite is optimized for mobile unless the developer
14852
+ // has explicitly opted in.
14853
+ if (reduceCallControlOptions.screenShareButton !== true) {
14854
+ reduceCallControlOptions.screenShareButton = false;
14873
14855
  }
14874
- dispose() {
14875
- this.unsubscribeAllEvents();
14856
+ return reduceCallControlOptions;
14857
+ };
14858
+ var CallEndReasons;
14859
+ (function (CallEndReasons) {
14860
+ CallEndReasons[CallEndReasons["LEFT_CALL"] = 0] = "LEFT_CALL";
14861
+ CallEndReasons[CallEndReasons["ACCESS_DENIED"] = 1] = "ACCESS_DENIED";
14862
+ CallEndReasons[CallEndReasons["REMOVED_FROM_CALL"] = 2] = "REMOVED_FROM_CALL";
14863
+ CallEndReasons[CallEndReasons["ROOM_NOT_FOUND"] = 3] = "ROOM_NOT_FOUND";
14864
+ CallEndReasons[CallEndReasons["DENIED_PERMISSION_TO_ROOM"] = 4] = "DENIED_PERMISSION_TO_ROOM";
14865
+ })(CallEndReasons || (CallEndReasons = {}));
14866
+ const getCallEndReason = (call) => {
14867
+ var _a, _b, _c, _d, _e;
14868
+ const remoteParticipantsEndedArray = Array.from(Object.values(call.remoteParticipantsEnded));
14869
+ /**
14870
+ * Handle the special case in a PSTN call where removing the last user kicks the caller out of the call.
14871
+ * The code and subcode is the same as when a user is removed from a teams interop call.
14872
+ * Hence, we look at the last remote participant removed to determine if the last participant removed was a phone number.
14873
+ * If yes, the caller was kicked out of the call, but we need to show them that they left the call.
14874
+ * Note: This check will only work for 1:1 PSTN Calls. The subcode is different for 1:N PSTN calls, and we do not need to handle that case.
14875
+ */
14876
+ if (remoteParticipantsEndedArray.length === 1 &&
14877
+ communicationCommon.isPhoneNumberIdentifier(remoteParticipantsEndedArray[0].identifier) &&
14878
+ ((_a = call.callEndReason) === null || _a === void 0 ? void 0 : _a.subCode) !== REMOTE_PSTN_USER_HUNG_UP) {
14879
+ return CallEndReasons.LEFT_CALL;
14876
14880
  }
14877
- fetchInitialData() {
14878
- return __awaiter$c(this, void 0, void 0, function* () {
14879
- // If get properties fails we dont want to try to get the participants after.
14880
- yield this.asyncTeeErrorToEventEmitter(() => __awaiter$c(this, void 0, void 0, function* () {
14881
- var e_1, _a;
14882
- yield this.chatThreadClient.getProperties();
14883
- try {
14884
- // Fetch all participants who joined before the local user.
14885
- for (var _b = __asyncValues(this.chatThreadClient.listParticipants().byPage({
14886
- // Fetch 100 participants per page by default.
14887
- maxPageSize: 100
14888
- // eslint-disable-next-line curly
14889
- })), _c; _c = yield _b.next(), !_c.done;) {
14890
- const _page = _c.value;
14891
- ;
14892
- }
14893
- }
14894
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
14895
- finally {
14896
- try {
14897
- if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
14898
- }
14899
- finally { if (e_1) throw e_1.error; }
14900
- }
14901
- }));
14902
- });
14881
+ if (((_b = call.callEndReason) === null || _b === void 0 ? void 0 : _b.subCode) && call.callEndReason.subCode === ACCESS_DENIED_TEAMS_MEETING_SUB_CODE) {
14882
+ return CallEndReasons.ACCESS_DENIED;
14903
14883
  }
14904
- getState() {
14905
- return this.context.getState();
14884
+ if (((_c = call.callEndReason) === null || _c === void 0 ? void 0 : _c.subCode) && REMOVED_FROM_CALL_SUB_CODES.includes(call.callEndReason.subCode)) {
14885
+ return CallEndReasons.REMOVED_FROM_CALL;
14906
14886
  }
14907
- onStateChange(handler) {
14908
- this.context.onStateChange(handler);
14887
+ /* @conditional-compile-remove(rooms) */
14888
+ if (((_d = call.callEndReason) === null || _d === void 0 ? void 0 : _d.subCode) && call.callEndReason.subCode === ROOM_NOT_FOUND_SUB_CODE) {
14889
+ return CallEndReasons.ROOM_NOT_FOUND;
14909
14890
  }
14910
- offStateChange(handler) {
14911
- this.context.offStateChange(handler);
14891
+ /* @conditional-compile-remove(rooms) */
14892
+ if (((_e = call.callEndReason) === null || _e === void 0 ? void 0 : _e.subCode) && call.callEndReason.subCode === DENIED_PERMISSION_TO_ROOM_SUB_CODE) {
14893
+ return CallEndReasons.DENIED_PERMISSION_TO_ROOM;
14912
14894
  }
14913
- sendMessage(content, options = {}) {
14914
- return __awaiter$c(this, void 0, void 0, function* () {
14915
- yield this.asyncTeeErrorToEventEmitter(() => __awaiter$c(this, void 0, void 0, function* () {
14916
- /* @conditional-compile-remove(file-sharing) */
14917
- options.metadata = Object.assign(Object.assign({}, options.metadata), convertFileUploadsUiStateToMessageMetadata(this.context.getState().fileUploads));
14918
- /* @conditional-compile-remove(file-sharing) */
14919
- /**
14920
- * All the current uploads need to be clear from the state before a message has been sent.
14921
- * This ensures the following behavior:
14922
- * 1. File Upload cards are removed from sendbox at the same time text in sendbox is removed.
14923
- * 2. any component rendering these file uploads doesn't continue to do so.
14924
- * 3. Cleans the state for new file uploads with a fresh message.
14925
- */
14926
- this.fileUploadAdapter.clearFileUploads();
14927
- yield this.handlers.onSendMessage(content, options);
14895
+ if (call.callEndReason) {
14896
+ // No error codes match, assume the user simply left the call regularly
14897
+ return CallEndReasons.LEFT_CALL;
14898
+ }
14899
+ throw new Error('No matching call end reason');
14900
+ };
14901
+ /**
14902
+ * Get the current call composite page based on the current call composite state
14903
+ *
14904
+ * @param Call - The current call state
14905
+ * @param previousCall - The state of the most recent previous call that has ended.
14906
+ *
14907
+ * @remarks - The previousCall state is needed to determine if the call has ended.
14908
+ * When the call ends a new call object is created, and so we must lookback at the
14909
+ * previous call state to understand how the call has ended. If there is no previous
14910
+ * call we know that this is a fresh call and can display the configuration page.
14911
+ *
14912
+ * @private
14913
+ */
14914
+ const getCallCompositePage = (call, previousCall, unsupportedBrowserInfo) => {
14915
+ /* @conditional-compile-remove(unsupported-browser) */
14916
+ if (isUnsupportedEnvironment(unsupportedBrowserInfo.features, unsupportedBrowserInfo.environmentInfo, unsupportedBrowserInfo.unsupportedBrowserVersionOptedIn)) {
14917
+ return 'unsupportedEnvironment';
14918
+ }
14919
+ if (call) {
14920
+ // Must check for ongoing call *before* looking at any previous calls.
14921
+ // If the composite completes one call and joins another, the previous calls
14922
+ // will be populated, but not relevant for determining the page.
14923
+ // `_isInLobbyOrConnecting` needs to be checked first because `_isInCall` also returns true when call is in lobby.
14924
+ if (_isInLobbyOrConnecting(call === null || call === void 0 ? void 0 : call.state)) {
14925
+ return 'lobby';
14926
+ // `LocalHold` needs to be checked before `isInCall` since it is also a state that's considered in call.
14927
+ }
14928
+ else if ((call === null || call === void 0 ? void 0 : call.state) === 'LocalHold') {
14929
+ /* @conditional-compile-remove(PSTN-calls) */ /* @conditional-compile-remove(one-to-n-calling) */
14930
+ return 'hold';
14931
+ }
14932
+ else if (_isInCall(call === null || call === void 0 ? void 0 : call.state)) {
14933
+ return 'call';
14934
+ }
14935
+ else {
14936
+ // When the call object has been constructed after clicking , but before 'connecting' has been
14937
+ // set on the call object, we continue to show the configuration screen.
14938
+ // The call object does not correctly reflect local device state until `call.state` moves to `connecting`.
14939
+ // Moving to the 'lobby' page too soon leads to components that depend on the `call` object to show incorrect
14940
+ // transitional state.
14941
+ return 'configuration';
14942
+ }
14943
+ }
14944
+ if (previousCall) {
14945
+ const reason = getCallEndReason(previousCall);
14946
+ /* @conditional-compile-remove(rooms) */
14947
+ switch (reason) {
14948
+ case CallEndReasons.ROOM_NOT_FOUND:
14949
+ return 'roomNotFound';
14950
+ case CallEndReasons.DENIED_PERMISSION_TO_ROOM:
14951
+ return 'deniedPermissionToRoom';
14952
+ }
14953
+ switch (reason) {
14954
+ case CallEndReasons.ACCESS_DENIED:
14955
+ return 'accessDeniedTeamsMeeting';
14956
+ case CallEndReasons.REMOVED_FROM_CALL:
14957
+ return 'removedFromCall';
14958
+ case CallEndReasons.LEFT_CALL:
14959
+ if (previousCall.diagnostics.network.latest.noNetwork) {
14960
+ return 'joinCallFailedDueToNoNetwork';
14961
+ }
14962
+ return 'leftCall';
14963
+ }
14964
+ }
14965
+ // No call state - show starting page (configuration)
14966
+ return 'configuration';
14967
+ };
14968
+ /** @private */
14969
+ const IsCallEndedPage = (
14970
+ /**
14971
+ * Explicitly listing the pages of this function intentionally.
14972
+ * This protects against adding a new composite page that should be marked as an callEndedPage.
14973
+ * EndCallPages are used to trigger onCallEnded events so this could easily be missed.
14974
+ * When you add a new composite page this will throw a compiler error. If this new page is an
14975
+ * EndCallPage ensure you update the END_CALL_PAGES. Afterwards update the `page` parameter
14976
+ * type below to allow your new page, i.e. add `| <your new page>
14977
+ */
14978
+ page) => END_CALL_PAGES.includes(page);
14979
+ /**
14980
+ * Creates a new call control options object and sets the correct values for disabling
14981
+ * the buttons provided in the `disabledControls` array.
14982
+ * Returns a new object without changing the original object.
14983
+ * @param callControlOptions options for the call control component that need to be modified.
14984
+ * @param disabledControls An array of controls to disable.
14985
+ * @returns a copy of callControlOptions with disabledControls disabled
14986
+ * @private
14987
+ */
14988
+ const disableCallControls = (callControlOptions, disabledControls) => {
14989
+ var _a;
14990
+ if (callControlOptions === false) {
14991
+ return false;
14992
+ }
14993
+ // Ensure we clone the prop if it is an object to ensure we do not mutate the original prop.
14994
+ let newOptions = (_a = (callControlOptions instanceof Object ? Object.assign({}, callControlOptions) : callControlOptions)) !== null && _a !== void 0 ? _a : {};
14995
+ if (newOptions === true || newOptions === undefined) {
14996
+ newOptions = disabledControls.reduce((acc, key) => {
14997
+ acc[key] = { disabled: true };
14998
+ return acc;
14999
+ }, {});
15000
+ }
15001
+ else {
15002
+ disabledControls.forEach((key) => {
15003
+ if (newOptions[key] !== false) {
15004
+ newOptions[key] = { disabled: true };
15005
+ }
15006
+ });
15007
+ }
15008
+ return newOptions;
15009
+ };
15010
+ /**
15011
+ * Check if a disabled object is provided for a button and returns if the button is disabled.
15012
+ * A button is only disabled if is explicitly set to disabled.
15013
+ *
15014
+ * @param option
15015
+ * @returns whether a button is disabled
15016
+ * @private
15017
+ */
15018
+ const isDisabled$2 = (option) => {
15019
+ if (option === undefined || typeof option === 'boolean') {
15020
+ return false;
15021
+ }
15022
+ return option.disabled;
15023
+ };
15024
+ /* @conditional-compile-remove(call-readiness) */
15025
+ /**
15026
+ *
15027
+ * This function uses permission API to determine if device permission state is granted, prompt or denied
15028
+ * @returns whether device permission state is granted, prompt or denied
15029
+ * If permission API is not supported on this browser, do nothing and log out error
15030
+ * @private
15031
+ */
15032
+ const getDevicePermissionState = (setVideoState, setAudioState) => {
15033
+ navigator.permissions
15034
+ .query({ name: 'camera' })
15035
+ .then((result) => {
15036
+ setVideoState(result.state);
15037
+ })
15038
+ .catch(() => {
15039
+ setVideoState('unsupported');
15040
+ });
15041
+ navigator.permissions
15042
+ .query({ name: 'microphone' })
15043
+ .then((result) => {
15044
+ setAudioState(result.state);
15045
+ })
15046
+ .catch(() => {
15047
+ setAudioState('unsupported');
15048
+ });
15049
+ };
15050
+ /* @conditional-compile-remove(unsupported-browser) */
15051
+ const isUnsupportedEnvironment = (features, environmentInfo, unsupportedBrowserVersionOptedIn) => {
15052
+ return !!((features === null || features === void 0 ? void 0 : features.unsupportedEnvironment) &&
15053
+ ((environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedBrowser) === false ||
15054
+ ((environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedBrowserVersion) === false && !unsupportedBrowserVersionOptedIn) ||
15055
+ (environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedPlatform) === false));
15056
+ };
15057
+ /**
15058
+ * Check if an object is identifier.
15059
+ *
15060
+ * @param identifier
15061
+ * @returns whether an identifier is one of identifier types (for runtime validation)
15062
+ * @private
15063
+ */
15064
+ const isValidIdentifier = (identifier) => {
15065
+ return (communicationCommon.isCommunicationUserIdentifier(identifier) ||
15066
+ communicationCommon.isPhoneNumberIdentifier(identifier) ||
15067
+ communicationCommon.isMicrosoftTeamsUserIdentifier(identifier) ||
15068
+ communicationCommon.isUnknownIdentifier(identifier));
15069
+ };
15070
+ /**
15071
+ * Check if we are using safari browser
15072
+ * @private
15073
+ */
15074
+ const _isSafari = (environmentInfo) => {
15075
+ /* @conditional-compile-remove(unsupported-browser) */
15076
+ return (environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.environment.browser) === 'safari';
15077
+ };
15078
+
15079
+ // Copyright (c) Microsoft Corporation.
15080
+ // Licensed under the MIT license.
15081
+ var __awaiter$c = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
15082
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15083
+ return new (P || (P = Promise))(function (resolve, reject) {
15084
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15085
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
15086
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
15087
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
15088
+ });
15089
+ };
15090
+ var __asyncValues = (window && window.__asyncValues) || function (o) {
15091
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
15092
+ var m = o[Symbol.asyncIterator], i;
15093
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
15094
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
15095
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
15096
+ };
15097
+ /**
15098
+ * Context of Chat, which is a centralized context for all state updates
15099
+ * @private
15100
+ */
15101
+ class ChatContext {
15102
+ constructor(clientState, threadId) {
15103
+ this.emitter = new EventEmitter__default['default']();
15104
+ const thread = clientState.threads[threadId];
15105
+ this.threadId = threadId;
15106
+ if (!thread) {
15107
+ throw 'Cannot find threadId, please initialize thread before use!';
15108
+ }
15109
+ this.state = {
15110
+ userId: clientState.userId,
15111
+ displayName: clientState.displayName,
15112
+ thread,
15113
+ latestErrors: clientState.latestErrors
15114
+ };
15115
+ }
15116
+ onStateChange(handler) {
15117
+ this.emitter.on('stateChanged', handler);
15118
+ }
15119
+ offStateChange(handler) {
15120
+ this.emitter.off('stateChanged', handler);
15121
+ }
15122
+ setState(state) {
15123
+ this.state = state;
15124
+ this.emitter.emit('stateChanged', this.state);
15125
+ }
15126
+ getState() {
15127
+ return this.state;
15128
+ }
15129
+ setError(error) {
15130
+ this.setState(Object.assign(Object.assign({}, this.state), { error }));
15131
+ }
15132
+ updateClientState(clientState) {
15133
+ const thread = clientState.threads[this.threadId];
15134
+ if (!thread) {
15135
+ throw 'Cannot find threadId, please make sure thread state is still in Stateful ChatClient.';
15136
+ }
15137
+ let updatedState = {
15138
+ userId: clientState.userId,
15139
+ displayName: clientState.displayName,
15140
+ thread,
15141
+ latestErrors: clientState.latestErrors
15142
+ };
15143
+ /* @conditional-compile-remove(file-sharing) */
15144
+ updatedState = Object.assign(Object.assign({}, updatedState), { fileUploads: this.state.fileUploads });
15145
+ this.setState(updatedState);
15146
+ }
15147
+ }
15148
+ /**
15149
+ * @private
15150
+ */
15151
+ class AzureCommunicationChatAdapter {
15152
+ constructor(chatClient, chatThreadClient) {
15153
+ this.emitter = new EventEmitter__default['default']();
15154
+ this.bindAllPublicMethods();
15155
+ this.chatClient = chatClient;
15156
+ this.chatThreadClient = chatThreadClient;
15157
+ this.context = new ChatContext(chatClient.getState(), chatThreadClient.threadId);
15158
+ /* @conditional-compile-remove(file-sharing) */
15159
+ this.fileUploadAdapter = new AzureCommunicationFileUploadAdapter(this.context);
15160
+ const onStateChange = (clientState) => {
15161
+ // unsubscribe when the instance gets disposed
15162
+ if (!this) {
15163
+ chatClient.offStateChange(onStateChange);
15164
+ return;
15165
+ }
15166
+ this.context.updateClientState(clientState);
15167
+ };
15168
+ this.handlers = createDefaultChatHandlers(chatClient, chatThreadClient);
15169
+ this.chatClient.onStateChange(onStateChange);
15170
+ this.subscribeAllEvents();
15171
+ }
15172
+ bindAllPublicMethods() {
15173
+ this.onStateChange = this.onStateChange.bind(this);
15174
+ this.offStateChange = this.offStateChange.bind(this);
15175
+ this.getState = this.getState.bind(this);
15176
+ this.dispose = this.dispose.bind(this);
15177
+ this.fetchInitialData = this.fetchInitialData.bind(this);
15178
+ this.sendMessage = this.sendMessage.bind(this);
15179
+ this.sendReadReceipt = this.sendReadReceipt.bind(this);
15180
+ this.sendTypingIndicator = this.sendTypingIndicator.bind(this);
15181
+ this.updateMessage = this.updateMessage.bind(this);
15182
+ this.deleteMessage = this.deleteMessage.bind(this);
15183
+ this.removeParticipant = this.removeParticipant.bind(this);
15184
+ this.setTopic = this.setTopic.bind(this);
15185
+ this.loadPreviousChatMessages = this.loadPreviousChatMessages.bind(this);
15186
+ this.on = this.on.bind(this);
15187
+ this.off = this.off.bind(this);
15188
+ /* @conditional-compile-remove(file-sharing) */
15189
+ this.registerActiveFileUploads = this.registerActiveFileUploads.bind(this);
15190
+ /* @conditional-compile-remove(file-sharing) */
15191
+ this.registerCompletedFileUploads = this.registerCompletedFileUploads.bind(this);
15192
+ /* @conditional-compile-remove(file-sharing) */
15193
+ this.clearFileUploads = this.clearFileUploads.bind(this);
15194
+ /* @conditional-compile-remove(file-sharing) */
15195
+ this.cancelFileUpload = this.cancelFileUpload.bind(this);
15196
+ /* @conditional-compile-remove(file-sharing) */
15197
+ this.updateFileUploadProgress = this.updateFileUploadProgress.bind(this);
15198
+ /* @conditional-compile-remove(file-sharing) */
15199
+ this.updateFileUploadErrorMessage = this.updateFileUploadErrorMessage.bind(this);
15200
+ /* @conditional-compile-remove(file-sharing) */
15201
+ this.updateFileUploadMetadata = this.updateFileUploadMetadata.bind(this);
15202
+ }
15203
+ dispose() {
15204
+ this.unsubscribeAllEvents();
15205
+ }
15206
+ fetchInitialData() {
15207
+ return __awaiter$c(this, void 0, void 0, function* () {
15208
+ // If get properties fails we dont want to try to get the participants after.
15209
+ yield this.asyncTeeErrorToEventEmitter(() => __awaiter$c(this, void 0, void 0, function* () {
15210
+ var e_1, _a;
15211
+ yield this.chatThreadClient.getProperties();
15212
+ try {
15213
+ // Fetch all participants who joined before the local user.
15214
+ for (var _b = __asyncValues(this.chatThreadClient.listParticipants().byPage({
15215
+ // Fetch 100 participants per page by default.
15216
+ maxPageSize: 100
15217
+ // eslint-disable-next-line curly
15218
+ })), _c; _c = yield _b.next(), !_c.done;) {
15219
+ const _page = _c.value;
15220
+ ;
15221
+ }
15222
+ }
15223
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
15224
+ finally {
15225
+ try {
15226
+ if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
15227
+ }
15228
+ finally { if (e_1) throw e_1.error; }
15229
+ }
15230
+ }));
15231
+ });
15232
+ }
15233
+ getState() {
15234
+ return this.context.getState();
15235
+ }
15236
+ onStateChange(handler) {
15237
+ this.context.onStateChange(handler);
15238
+ }
15239
+ offStateChange(handler) {
15240
+ this.context.offStateChange(handler);
15241
+ }
15242
+ sendMessage(content, options = {}) {
15243
+ return __awaiter$c(this, void 0, void 0, function* () {
15244
+ yield this.asyncTeeErrorToEventEmitter(() => __awaiter$c(this, void 0, void 0, function* () {
15245
+ /* @conditional-compile-remove(file-sharing) */
15246
+ options.metadata = Object.assign(Object.assign({}, options.metadata), convertFileUploadsUiStateToMessageMetadata(this.context.getState().fileUploads));
15247
+ /* @conditional-compile-remove(file-sharing) */
15248
+ /**
15249
+ * All the current uploads need to be clear from the state before a message has been sent.
15250
+ * This ensures the following behavior:
15251
+ * 1. File Upload cards are removed from sendbox at the same time text in sendbox is removed.
15252
+ * 2. any component rendering these file uploads doesn't continue to do so.
15253
+ * 3. Cleans the state for new file uploads with a fresh message.
15254
+ */
15255
+ this.fileUploadAdapter.clearFileUploads();
15256
+ yield this.handlers.onSendMessage(content, options);
14928
15257
  }));
14929
15258
  });
14930
15259
  }
@@ -15097,6 +15426,9 @@ const convertEventType = (type) => {
15097
15426
  * @public
15098
15427
  */
15099
15428
  const createAzureCommunicationChatAdapter = ({ endpoint: endpointUrl, userId, displayName, credential, threadId }) => __awaiter$c(void 0, void 0, void 0, function* () {
15429
+ if (!isValidIdentifier(userId)) {
15430
+ throw new Error('Provided userId is invalid. Please provide valid identifier object.');
15431
+ }
15100
15432
  const chatClient = createStatefulChatClient({
15101
15433
  userId,
15102
15434
  displayName,
@@ -15873,400 +16205,147 @@ const ChatScreen = (props) => {
15873
16205
  React__default['default'].createElement(SendBox, Object.assign({}, sendBoxProps, { autoFocus: options === null || options === void 0 ? void 0 : options.autoFocus, styles: sendBoxStyles,
15874
16206
  /* @conditional-compile-remove(file-sharing) */
15875
16207
  activeFileUploads: useSelector$2(fileUploadsSelector).files,
15876
- /* @conditional-compile-remove(file-sharing) */
15877
- onCancelFileUpload: adapter.cancelFileUpload }))),
15878
- formFactor !== 'mobile' && React__default['default'].createElement(AttachFileButton, null)))),
15879
- /* @conditional-compile-remove(chat-composite-participant-pane) */
15880
- (options === null || options === void 0 ? void 0 : options.participantPane) === true && (React__default['default'].createElement(ChatScreenPeoplePane, { onFetchAvatarPersonaData: onFetchAvatarPersonaData, onFetchParticipantMenuItems: props.onFetchParticipantMenuItems, isMobile: formFactor === 'mobile' })))));
15881
- };
15882
-
15883
- // Copyright (c) Microsoft Corporation.
15884
- /**
15885
- * A customizable UI composite for the chat experience.
15886
- *
15887
- * @remarks Chat composite min width and height are respectively 17.5rem and 20rem (280px and 320px, with default rem at 16px)
15888
- *
15889
- * @public
15890
- */
15891
- const ChatComposite = (props) => {
15892
- const { adapter, options, onFetchAvatarPersonaData, onRenderTypingIndicator, onRenderMessage, onFetchParticipantMenuItems } = props;
15893
- const formFactor = props['formFactor'] || 'desktop';
15894
- /**
15895
- * @TODO Remove this function and pass the props directly when file-sharing is promoted to stable.
15896
- * @private
15897
- */
15898
- // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
15899
- const fileSharingOptions = () => {
15900
- /* @conditional-compile-remove(file-sharing) */
15901
- return {
15902
- fileSharing: options === null || options === void 0 ? void 0 : options.fileSharing
15903
- };
15904
- };
15905
- return (React__default['default'].createElement("div", { className: chatScreenContainerStyle },
15906
- React__default['default'].createElement(BaseProvider, Object.assign({}, props),
15907
- React__default['default'].createElement(ChatAdapterProvider, { adapter: adapter },
15908
- React__default['default'].createElement(ChatScreen, Object.assign({ formFactor: formFactor, options: options, onFetchAvatarPersonaData: onFetchAvatarPersonaData, onRenderTypingIndicator: onRenderTypingIndicator, onRenderMessage: onRenderMessage, onFetchParticipantMenuItems: onFetchParticipantMenuItems }, fileSharingOptions()))))));
15909
- };
15910
-
15911
- // Copyright (c) Microsoft Corporation.
15912
- const CallAdapterContext = React.createContext(undefined);
15913
- /**
15914
- * @private
15915
- */
15916
- const CallAdapterProvider = (props) => {
15917
- const { adapter } = props;
15918
- return React__default['default'].createElement(CallAdapterContext.Provider, { value: adapter }, props.children);
15919
- };
15920
- /**
15921
- * @private
15922
- */
15923
- const useAdapter = () => {
15924
- const adapter = React.useContext(CallAdapterContext);
15925
- if (!adapter) {
15926
- throw 'Cannot find adapter please initialize before usage.';
15927
- }
15928
- return adapter;
15929
- };
15930
-
15931
- // Copyright (c) Microsoft Corporation.
15932
- // Licensed under the MIT license.
15933
- /** @private */
15934
- const containerDivStyles = { position: 'relative', width: '100%', height: '100%' };
15935
-
15936
- // Copyright (c) Microsoft Corporation.
15937
- /**
15938
- * @private
15939
- */
15940
- const useAdaptedSelector = (selector, selectorProps) => {
15941
- return useSelectorWithAdaptation(selector, adaptCompositeState, selectorProps);
15942
- };
15943
- /**
15944
- * @private
15945
- */
15946
- const useSelectorWithAdaptation = (selector, adaptState, selectorProps) => {
15947
- var _a;
15948
- const adapter = useAdapter();
15949
- // Keeps track of whether the current component is mounted or not. If it has unmounted, make sure we do not modify the
15950
- // state or it will cause React warnings in the console. https://skype.visualstudio.com/SPOOL/_workitems/edit/2453212
15951
- const mounted = React.useRef(false);
15952
- React.useEffect(() => {
15953
- mounted.current = true;
15954
- return () => {
15955
- mounted.current = false;
15956
- };
15957
- });
15958
- const callId = (_a = adapter.getState().call) === null || _a === void 0 ? void 0 : _a.id;
15959
- const callConfigProps = React.useMemo(() => ({
15960
- callId
15961
- }), [callId]);
15962
- const [props, setProps] = React.useState(selector(adaptState(adapter.getState()), selectorProps !== null && selectorProps !== void 0 ? selectorProps : callConfigProps));
15963
- const propRef = React.useRef(props);
15964
- propRef.current = props;
15965
- React.useEffect(() => {
15966
- const onStateChange = (state) => {
15967
- if (!mounted.current) {
15968
- return;
15969
- }
15970
- const newProps = selector(adaptState(state), selectorProps !== null && selectorProps !== void 0 ? selectorProps : callConfigProps);
15971
- if (propRef.current !== newProps) {
15972
- setProps(newProps);
15973
- }
15974
- };
15975
- adapter.onStateChange(onStateChange);
15976
- return () => {
15977
- adapter.offStateChange(onStateChange);
15978
- };
15979
- }, [adaptState, adapter, selector, selectorProps, callConfigProps]);
15980
- return props;
15981
- };
15982
- const memoizeState = memoizeOne__default['default']((userId, deviceManager, calls, latestErrors, displayName) => ({
15983
- userId,
15984
- incomingCalls: {},
15985
- incomingCallsEnded: {},
15986
- callsEnded: {},
15987
- deviceManager,
15988
- callAgent: { displayName },
15989
- calls,
15990
- latestErrors
15991
- }));
15992
- const memoizeCalls = memoizeOne__default['default']((call) => (call ? { [call.id]: call } : {}));
15993
- const adaptCompositeState = (compositeState) => {
15994
- return memoizeState(compositeState.userId, compositeState.devices, memoizeCalls(compositeState.call),
15995
- // This is an unsafe type expansion.
15996
- // compositeState.latestErrors can contain properties that are not valid in CallErrors.
15997
- //
15998
- // But there is no way to check for valid property names at runtime:
15999
- // - The set of valid property names is built from types in the @azure/communication-calling.
16000
- // Thus we don't have a literal array of allowed strings at runtime.
16001
- // - Due to minification / uglification, the property names from the objects at runtime can't be used
16002
- // to compare against permissible values inferred from the types.
16003
- //
16004
- // This is not a huge problem -- it simply means that our adapted selector will include some extra operations
16005
- // that are unknown to the UI component and data binding libraries. Generic handling of the errors (e.g.,
16006
- // just displaying them in some UI surface) will continue to work for these operations. Handling of
16007
- // specific operations (e.g., acting on errors related to permission issues) will ignore these operations.
16008
- compositeState.latestErrors, compositeState.displayName);
16009
- };
16010
-
16011
- // Copyright (c) Microsoft Corporation.
16012
- // Licensed under the MIT license.
16013
- /**
16014
- * Subset of CallCompositePages that represent an end call state.
16015
- * @private
16016
- */
16017
- const END_CALL_PAGES = [
16018
- 'accessDeniedTeamsMeeting',
16019
- 'joinCallFailedDueToNoNetwork',
16020
- 'leftCall',
16021
- /* @conditional-compile-remove(rooms) */ 'deniedPermissionToRoom',
16022
- 'removedFromCall',
16023
- /* @conditional-compile-remove(rooms) */ 'roomNotFound',
16024
- /* @conditional-compile-remove(unsupported-browser) */ 'unsupportedEnvironment'
16025
- ];
16026
-
16027
- // Copyright (c) Microsoft Corporation.
16028
- const ACCESS_DENIED_TEAMS_MEETING_SUB_CODE = 5854;
16029
- const REMOTE_PSTN_USER_HUNG_UP = 560000;
16030
- const REMOVED_FROM_CALL_SUB_CODES = [5000, 5300, REMOTE_PSTN_USER_HUNG_UP];
16031
- /* @conditional-compile-remove(rooms) */
16032
- const ROOM_NOT_FOUND_SUB_CODE = 5751;
16033
- /* @conditional-compile-remove(rooms) */
16034
- const DENIED_PERMISSION_TO_ROOM_SUB_CODE = 5828;
16035
- /**
16036
- * @private
16037
- */
16038
- const isCameraOn = (state) => {
16039
- if (state.call) {
16040
- const stream = state.call.localVideoStreams.find((stream) => stream.mediaStreamType === 'Video');
16041
- return !!stream;
16042
- }
16043
- else {
16044
- if (state.devices.selectedCamera) {
16045
- const previewOn = _isPreviewOn(state.devices);
16046
- return previewOn;
16047
- }
16048
- }
16049
- return false;
16050
- };
16051
- /**
16052
- * Reduce the set of call controls visible on mobile.
16053
- * For example do not show screenshare button.
16054
- *
16055
- * @private
16056
- */
16057
- const reduceCallControlsForMobile = (callControlOptions) => {
16058
- if (callControlOptions === false) {
16059
- return false;
16060
- }
16061
- // Ensure call controls a valid object.
16062
- const reduceCallControlOptions = callControlOptions === true ? {} : callControlOptions || {};
16063
- // Set to compressed mode when composite is optimized for mobile
16064
- reduceCallControlOptions.displayType = 'compact';
16065
- // Do not show screen share button when composite is optimized for mobile unless the developer
16066
- // has explicitly opted in.
16067
- if (reduceCallControlOptions.screenShareButton !== true) {
16068
- reduceCallControlOptions.screenShareButton = false;
16069
- }
16070
- return reduceCallControlOptions;
16071
- };
16072
- var CallEndReasons;
16073
- (function (CallEndReasons) {
16074
- CallEndReasons[CallEndReasons["LEFT_CALL"] = 0] = "LEFT_CALL";
16075
- CallEndReasons[CallEndReasons["ACCESS_DENIED"] = 1] = "ACCESS_DENIED";
16076
- CallEndReasons[CallEndReasons["REMOVED_FROM_CALL"] = 2] = "REMOVED_FROM_CALL";
16077
- CallEndReasons[CallEndReasons["ROOM_NOT_FOUND"] = 3] = "ROOM_NOT_FOUND";
16078
- CallEndReasons[CallEndReasons["DENIED_PERMISSION_TO_ROOM"] = 4] = "DENIED_PERMISSION_TO_ROOM";
16079
- })(CallEndReasons || (CallEndReasons = {}));
16080
- const getCallEndReason = (call) => {
16081
- var _a, _b, _c, _d, _e;
16082
- const remoteParticipantsEndedArray = Array.from(Object.values(call.remoteParticipantsEnded));
16083
- /**
16084
- * Handle the special case in a PSTN call where removing the last user kicks the caller out of the call.
16085
- * The code and subcode is the same as when a user is removed from a teams interop call.
16086
- * Hence, we look at the last remote participant removed to determine if the last participant removed was a phone number.
16087
- * If yes, the caller was kicked out of the call, but we need to show them that they left the call.
16088
- * Note: This check will only work for 1:1 PSTN Calls. The subcode is different for 1:N PSTN calls, and we do not need to handle that case.
16089
- */
16090
- if (remoteParticipantsEndedArray.length === 1 &&
16091
- communicationCommon.isPhoneNumberIdentifier(remoteParticipantsEndedArray[0].identifier) &&
16092
- ((_a = call.callEndReason) === null || _a === void 0 ? void 0 : _a.subCode) !== REMOTE_PSTN_USER_HUNG_UP) {
16093
- return CallEndReasons.LEFT_CALL;
16094
- }
16095
- if (((_b = call.callEndReason) === null || _b === void 0 ? void 0 : _b.subCode) && call.callEndReason.subCode === ACCESS_DENIED_TEAMS_MEETING_SUB_CODE) {
16096
- return CallEndReasons.ACCESS_DENIED;
16097
- }
16098
- if (((_c = call.callEndReason) === null || _c === void 0 ? void 0 : _c.subCode) && REMOVED_FROM_CALL_SUB_CODES.includes(call.callEndReason.subCode)) {
16099
- return CallEndReasons.REMOVED_FROM_CALL;
16100
- }
16101
- /* @conditional-compile-remove(rooms) */
16102
- if (((_d = call.callEndReason) === null || _d === void 0 ? void 0 : _d.subCode) && call.callEndReason.subCode === ROOM_NOT_FOUND_SUB_CODE) {
16103
- return CallEndReasons.ROOM_NOT_FOUND;
16104
- }
16105
- /* @conditional-compile-remove(rooms) */
16106
- if (((_e = call.callEndReason) === null || _e === void 0 ? void 0 : _e.subCode) && call.callEndReason.subCode === DENIED_PERMISSION_TO_ROOM_SUB_CODE) {
16107
- return CallEndReasons.DENIED_PERMISSION_TO_ROOM;
16108
- }
16109
- if (call.callEndReason) {
16110
- // No error codes match, assume the user simply left the call regularly
16111
- return CallEndReasons.LEFT_CALL;
16112
- }
16113
- throw new Error('No matching call end reason');
16208
+ /* @conditional-compile-remove(file-sharing) */
16209
+ onCancelFileUpload: adapter.cancelFileUpload }))),
16210
+ formFactor !== 'mobile' && React__default['default'].createElement(AttachFileButton, null)))),
16211
+ /* @conditional-compile-remove(chat-composite-participant-pane) */
16212
+ (options === null || options === void 0 ? void 0 : options.participantPane) === true && (React__default['default'].createElement(ChatScreenPeoplePane, { onFetchAvatarPersonaData: onFetchAvatarPersonaData, onFetchParticipantMenuItems: props.onFetchParticipantMenuItems, isMobile: formFactor === 'mobile' })))));
16114
16213
  };
16214
+
16215
+ // Copyright (c) Microsoft Corporation.
16115
16216
  /**
16116
- * Get the current call composite page based on the current call composite state
16117
- *
16118
- * @param Call - The current call state
16119
- * @param previousCall - The state of the most recent previous call that has ended.
16217
+ * A customizable UI composite for the chat experience.
16120
16218
  *
16121
- * @remarks - The previousCall state is needed to determine if the call has ended.
16122
- * When the call ends a new call object is created, and so we must lookback at the
16123
- * previous call state to understand how the call has ended. If there is no previous
16124
- * call we know that this is a fresh call and can display the configuration page.
16219
+ * @remarks Chat composite min width and height are respectively 17.5rem and 20rem (280px and 320px, with default rem at 16px)
16125
16220
  *
16126
- * @private
16221
+ * @public
16127
16222
  */
16128
- const getCallCompositePage = (call, previousCall, unsupportedBrowserInfo) => {
16129
- /* @conditional-compile-remove(unsupported-browser) */
16130
- if (isUnsupportedEnvironment(unsupportedBrowserInfo.features, unsupportedBrowserInfo.environmentInfo, unsupportedBrowserInfo.unsupportedBrowserVersionOptedIn)) {
16131
- return 'unsupportedEnvironment';
16132
- }
16133
- if (call) {
16134
- // Must check for ongoing call *before* looking at any previous calls.
16135
- // If the composite completes one call and joins another, the previous calls
16136
- // will be populated, but not relevant for determining the page.
16137
- // `_isInLobbyOrConnecting` needs to be checked first because `_isInCall` also returns true when call is in lobby.
16138
- if (_isInLobbyOrConnecting(call === null || call === void 0 ? void 0 : call.state)) {
16139
- return 'lobby';
16140
- // `LocalHold` needs to be checked before `isInCall` since it is also a state that's considered in call.
16141
- }
16142
- else if ((call === null || call === void 0 ? void 0 : call.state) === 'LocalHold') {
16143
- /* @conditional-compile-remove(PSTN-calls) */ /* @conditional-compile-remove(one-to-n-calling) */
16144
- return 'hold';
16145
- }
16146
- else if (_isInCall(call === null || call === void 0 ? void 0 : call.state)) {
16147
- return 'call';
16148
- }
16149
- else {
16150
- // When the call object has been constructed after clicking , but before 'connecting' has been
16151
- // set on the call object, we continue to show the configuration screen.
16152
- // The call object does not correctly reflect local device state until `call.state` moves to `connecting`.
16153
- // Moving to the 'lobby' page too soon leads to components that depend on the `call` object to show incorrect
16154
- // transitional state.
16155
- return 'configuration';
16156
- }
16157
- }
16158
- if (previousCall) {
16159
- const reason = getCallEndReason(previousCall);
16160
- /* @conditional-compile-remove(rooms) */
16161
- switch (reason) {
16162
- case CallEndReasons.ROOM_NOT_FOUND:
16163
- return 'roomNotFound';
16164
- case CallEndReasons.DENIED_PERMISSION_TO_ROOM:
16165
- return 'deniedPermissionToRoom';
16166
- }
16167
- switch (reason) {
16168
- case CallEndReasons.ACCESS_DENIED:
16169
- return 'accessDeniedTeamsMeeting';
16170
- case CallEndReasons.REMOVED_FROM_CALL:
16171
- return 'removedFromCall';
16172
- case CallEndReasons.LEFT_CALL:
16173
- if (previousCall.diagnostics.network.latest.noNetwork) {
16174
- return 'joinCallFailedDueToNoNetwork';
16175
- }
16176
- return 'leftCall';
16177
- }
16178
- }
16179
- // No call state - show starting page (configuration)
16180
- return 'configuration';
16223
+ const ChatComposite = (props) => {
16224
+ const { adapter, options, onFetchAvatarPersonaData, onRenderTypingIndicator, onRenderMessage, onFetchParticipantMenuItems } = props;
16225
+ const formFactor = props['formFactor'] || 'desktop';
16226
+ /**
16227
+ * @TODO Remove this function and pass the props directly when file-sharing is promoted to stable.
16228
+ * @private
16229
+ */
16230
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
16231
+ const fileSharingOptions = () => {
16232
+ /* @conditional-compile-remove(file-sharing) */
16233
+ return {
16234
+ fileSharing: options === null || options === void 0 ? void 0 : options.fileSharing
16235
+ };
16236
+ };
16237
+ return (React__default['default'].createElement("div", { className: chatScreenContainerStyle },
16238
+ React__default['default'].createElement(BaseProvider, Object.assign({}, props),
16239
+ React__default['default'].createElement(ChatAdapterProvider, { adapter: adapter },
16240
+ React__default['default'].createElement(ChatScreen, Object.assign({ formFactor: formFactor, options: options, onFetchAvatarPersonaData: onFetchAvatarPersonaData, onRenderTypingIndicator: onRenderTypingIndicator, onRenderMessage: onRenderMessage, onFetchParticipantMenuItems: onFetchParticipantMenuItems }, fileSharingOptions()))))));
16181
16241
  };
16182
- /** @private */
16183
- const IsCallEndedPage = (
16242
+
16243
+ // Copyright (c) Microsoft Corporation.
16244
+ const CallAdapterContext = React.createContext(undefined);
16184
16245
  /**
16185
- * Explicitly listing the pages of this function intentionally.
16186
- * This protects against adding a new composite page that should be marked as an callEndedPage.
16187
- * EndCallPages are used to trigger onCallEnded events so this could easily be missed.
16188
- * When you add a new composite page this will throw a compiler error. If this new page is an
16189
- * EndCallPage ensure you update the END_CALL_PAGES. Afterwards update the `page` parameter
16190
- * type below to allow your new page, i.e. add `| <your new page>
16246
+ * @private
16191
16247
  */
16192
- page) => END_CALL_PAGES.includes(page);
16248
+ const CallAdapterProvider = (props) => {
16249
+ const { adapter } = props;
16250
+ return React__default['default'].createElement(CallAdapterContext.Provider, { value: adapter }, props.children);
16251
+ };
16193
16252
  /**
16194
- * Creates a new call control options object and sets the correct values for disabling
16195
- * the buttons provided in the `disabledControls` array.
16196
- * Returns a new object without changing the original object.
16197
- * @param callControlOptions options for the call control component that need to be modified.
16198
- * @param disabledControls An array of controls to disable.
16199
- * @returns a copy of callControlOptions with disabledControls disabled
16200
16253
  * @private
16201
16254
  */
16202
- const disableCallControls = (callControlOptions, disabledControls) => {
16203
- var _a;
16204
- if (callControlOptions === false) {
16205
- return false;
16206
- }
16207
- // Ensure we clone the prop if it is an object to ensure we do not mutate the original prop.
16208
- let newOptions = (_a = (callControlOptions instanceof Object ? Object.assign({}, callControlOptions) : callControlOptions)) !== null && _a !== void 0 ? _a : {};
16209
- if (newOptions === true || newOptions === undefined) {
16210
- newOptions = disabledControls.reduce((acc, key) => {
16211
- acc[key] = { disabled: true };
16212
- return acc;
16213
- }, {});
16214
- }
16215
- else {
16216
- disabledControls.forEach((key) => {
16217
- if (newOptions[key] !== false) {
16218
- newOptions[key] = { disabled: true };
16219
- }
16220
- });
16255
+ const useAdapter = () => {
16256
+ const adapter = React.useContext(CallAdapterContext);
16257
+ if (!adapter) {
16258
+ throw 'Cannot find adapter please initialize before usage.';
16221
16259
  }
16222
- return newOptions;
16260
+ return adapter;
16223
16261
  };
16262
+
16263
+ // Copyright (c) Microsoft Corporation.
16264
+ // Licensed under the MIT license.
16265
+ /** @private */
16266
+ const containerDivStyles = { position: 'relative', width: '100%', height: '100%' };
16267
+
16268
+ // Copyright (c) Microsoft Corporation.
16224
16269
  /**
16225
- * Check if a disabled object is provided for a button and returns if the button is disabled.
16226
- * A button is only disabled if is explicitly set to disabled.
16227
- *
16228
- * @param option
16229
- * @returns whether a button is disabled
16230
16270
  * @private
16231
16271
  */
16232
- const isDisabled$2 = (option) => {
16233
- if (option === undefined || typeof option === 'boolean') {
16234
- return false;
16235
- }
16236
- return option.disabled;
16272
+ const useAdaptedSelector = (selector, selectorProps) => {
16273
+ return useSelectorWithAdaptation(selector, adaptCompositeState, selectorProps);
16237
16274
  };
16238
- /* @conditional-compile-remove(call-readiness) */
16239
16275
  /**
16240
- *
16241
- * This function uses permission API to determine if device permission state is granted, prompt or denied
16242
- * @returns whether device permission state is granted, prompt or denied
16243
- * If permission API is not supported on this browser, do nothing and log out error
16244
16276
  * @private
16245
16277
  */
16246
- const getDevicePermissionState = (setVideoState, setAudioState) => {
16247
- navigator.permissions
16248
- .query({ name: 'camera' })
16249
- .then((result) => {
16250
- setVideoState(result.state);
16251
- })
16252
- .catch(() => {
16253
- setVideoState('unsupported');
16254
- });
16255
- navigator.permissions
16256
- .query({ name: 'microphone' })
16257
- .then((result) => {
16258
- setAudioState(result.state);
16259
- })
16260
- .catch(() => {
16261
- setAudioState('unsupported');
16278
+ const useSelectorWithAdaptation = (selector, adaptState, selectorProps) => {
16279
+ var _a;
16280
+ const adapter = useAdapter();
16281
+ // Keeps track of whether the current component is mounted or not. If it has unmounted, make sure we do not modify the
16282
+ // state or it will cause React warnings in the console. https://skype.visualstudio.com/SPOOL/_workitems/edit/2453212
16283
+ const mounted = React.useRef(false);
16284
+ React.useEffect(() => {
16285
+ mounted.current = true;
16286
+ return () => {
16287
+ mounted.current = false;
16288
+ };
16262
16289
  });
16290
+ const callId = (_a = adapter.getState().call) === null || _a === void 0 ? void 0 : _a.id;
16291
+ const callConfigProps = React.useMemo(() => ({
16292
+ callId
16293
+ }), [callId]);
16294
+ const [props, setProps] = React.useState(selector(adaptState(adapter.getState()), selectorProps !== null && selectorProps !== void 0 ? selectorProps : callConfigProps));
16295
+ const propRef = React.useRef(props);
16296
+ propRef.current = props;
16297
+ React.useEffect(() => {
16298
+ const onStateChange = (state) => {
16299
+ if (!mounted.current) {
16300
+ return;
16301
+ }
16302
+ const newProps = selector(adaptState(state), selectorProps !== null && selectorProps !== void 0 ? selectorProps : callConfigProps);
16303
+ if (propRef.current !== newProps) {
16304
+ setProps(newProps);
16305
+ }
16306
+ };
16307
+ adapter.onStateChange(onStateChange);
16308
+ return () => {
16309
+ adapter.offStateChange(onStateChange);
16310
+ };
16311
+ }, [adaptState, adapter, selector, selectorProps, callConfigProps]);
16312
+ return props;
16263
16313
  };
16264
- /* @conditional-compile-remove(unsupported-browser) */
16265
- const isUnsupportedEnvironment = (features, environmentInfo, unsupportedBrowserVersionOptedIn) => {
16266
- return !!((features === null || features === void 0 ? void 0 : features.unsupportedEnvironment) &&
16267
- ((environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedBrowser) === false ||
16268
- ((environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedBrowserVersion) === false && !unsupportedBrowserVersionOptedIn) ||
16269
- (environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedPlatform) === false));
16314
+ const memoizeState = memoizeOne__default['default']((userId, deviceManager, calls, latestErrors, displayName, alternateCallerId, environmentInfo) => ({
16315
+ userId,
16316
+ incomingCalls: {},
16317
+ incomingCallsEnded: {},
16318
+ callsEnded: {},
16319
+ deviceManager,
16320
+ callAgent: { displayName },
16321
+ calls,
16322
+ latestErrors,
16323
+ /* @conditional-compile-remove(PSTN-calls) */
16324
+ alternateCallerId,
16325
+ /* @conditional-compile-remove(unsupported-browser) */
16326
+ environmentInfo
16327
+ }));
16328
+ const memoizeCalls = memoizeOne__default['default']((call) => (call ? { [call.id]: call } : {}));
16329
+ const adaptCompositeState = (compositeState) => {
16330
+ return memoizeState(compositeState.userId, compositeState.devices, memoizeCalls(compositeState.call),
16331
+ // This is an unsafe type expansion.
16332
+ // compositeState.latestErrors can contain properties that are not valid in CallErrors.
16333
+ //
16334
+ // But there is no way to check for valid property names at runtime:
16335
+ // - The set of valid property names is built from types in the @azure/communication-calling.
16336
+ // Thus we don't have a literal array of allowed strings at runtime.
16337
+ // - Due to minification / uglification, the property names from the objects at runtime can't be used
16338
+ // to compare against permissible values inferred from the types.
16339
+ //
16340
+ // This is not a huge problem -- it simply means that our adapted selector will include some extra operations
16341
+ // that are unknown to the UI component and data binding libraries. Generic handling of the errors (e.g.,
16342
+ // just displaying them in some UI surface) will continue to work for these operations. Handling of
16343
+ // specific operations (e.g., acting on errors related to permission issues) will ignore these operations.
16344
+ compositeState.latestErrors, compositeState.displayName,
16345
+ /* @conditional-compile-remove(PSTN-calls) */
16346
+ compositeState.alternateCallerId,
16347
+ /* @conditional-compile-remove(unsupported-browser) */
16348
+ compositeState.environmentInfo);
16270
16349
  };
16271
16350
 
16272
16351
  // Copyright (c) Microsoft Corporation.
@@ -17682,7 +17761,21 @@ function PeoplePaneAddPersonIconTrampoline() {
17682
17761
  const AddPeopleButton = (props) => {
17683
17762
  const { inviteLink, mobileView, strings, participantList } = props;
17684
17763
  const theme = react.useTheme();
17764
+ const [copyInviteLinkAnnouncerStrings, setCopyInviteLinkAnnouncerStrings] = React.useState('');
17685
17765
  React.useMemo(() => react.concatStyleSets(copyLinkButtonStyles, themedCopyLinkButtonStyles$1(mobileView, theme)), [mobileView, theme]);
17766
+ /**
17767
+ * sets the announcement string for when the link is copied.
17768
+ */
17769
+ React.useCallback(() => {
17770
+ setCopyInviteLinkAnnouncerStrings(strings.copyInviteLinkActionedAriaLabel);
17771
+ /**
17772
+ * Clears the announcer string after the user clicks the
17773
+ * copyInviteLink button allowing it to be re-announced.
17774
+ */
17775
+ setTimeout(() => {
17776
+ setCopyInviteLinkAnnouncerStrings('');
17777
+ }, 3000);
17778
+ }, [strings.copyInviteLinkActionedAriaLabel]);
17686
17779
  /* @conditional-compile-remove(PSTN-calls) */
17687
17780
  if (mobileView) {
17688
17781
  return (React__default['default'].createElement(AddPeopleDropdown, { strings: strings, mobileView: mobileView, inviteLink: inviteLink, onAddParticipant: props.onAddParticipant, alternateCallerId: props.alternateCallerId }));
@@ -18085,7 +18178,7 @@ const CallArrangement = (props) => {
18085
18178
  /* @conditional-compile-remove(rooms) */
18086
18179
  // TODO: move this logic to the error bar selector once role is plumbed from the headless SDK
18087
18180
  if (!rolePermissions.cameraButton && props.errorBarProps) {
18088
- errorBarProps = Object.assign(Object.assign({}, props.errorBarProps), { activeErrorMessages: props.errorBarProps.activeErrorMessages.filter((e) => e.type !== 'callCameraAccessDenied') });
18181
+ errorBarProps = Object.assign(Object.assign({}, props.errorBarProps), { activeErrorMessages: props.errorBarProps.activeErrorMessages.filter((e) => e.type !== 'callCameraAccessDenied' && e.type !== 'callCameraAccessDeniedSafari') });
18089
18182
  }
18090
18183
  return (React__default['default'].createElement("div", { ref: containerRef, className: react.mergeStyles(containerDivStyles) },
18091
18184
  React__default['default'].createElement(react.Stack, { verticalFill: true, horizontalAlign: "stretch", className: containerClassName, "data-ui-id": props.dataUiId },
@@ -19063,18 +19156,26 @@ const DRAWER_HIGH_Z_BAND = 99; // setting z index to 99 so that it sit above al
19063
19156
  * @private
19064
19157
  */
19065
19158
  const CallReadinessModal = (props) => {
19066
- const { mobileView, audioState, videoState, permissionsState, isPermissionsModalDismissed, setIsPermissionsModalDismissed, onPermissionsTroubleshootingClick } = props;
19159
+ const { mobileView, permissionsState,
19160
+ /* @conditional-compile-remove(unsupported-browser) */ environmentInfo, isPermissionsModalDismissed, setIsPermissionsModalDismissed, onPermissionsTroubleshootingClick } = props;
19067
19161
  const onLightDismissTriggered = () => {
19068
19162
  // do nothing here
19069
19163
  // only way to dismiss this drawer is clicking on allow access which will leads to device permission prompt
19070
19164
  };
19165
+ // On Safari browser with 2 options: don't allow/never for this website again, when don't allow is clicked, permissionAPI returns prompt and PermissionGranted from calling sdk returns false (the right value)
19166
+ const videoState = permissionsState.camera;
19167
+ const audioState = permissionsState.microphone;
19071
19168
  const showModal = videoState === 'denied' || videoState === 'prompt' || audioState === 'denied' || audioState === 'prompt';
19169
+ /* @conditional-compile-remove(unsupported-browser) */
19170
+ const isSafari = _isSafari(environmentInfo);
19072
19171
  const modal = !showModal
19073
19172
  ? undefined
19074
19173
  : () => {
19075
19174
  // if both video and audio permission are not set
19076
19175
  if (videoState === 'prompt' && audioState === 'prompt') {
19077
- return (React__default['default'].createElement(CameraAndMicrophoneDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19176
+ return (React__default['default'].createElement(CameraAndMicrophoneDomainPermissions, { appName: 'app',
19177
+ /* @conditional-compile-remove(unsupported-browser) */
19178
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19078
19179
  ? () => {
19079
19180
  onPermissionsTroubleshootingClick(permissionsState);
19080
19181
  }
@@ -19082,7 +19183,9 @@ const CallReadinessModal = (props) => {
19082
19183
  }
19083
19184
  // if audio permission is set up but video is not
19084
19185
  else if (videoState === 'prompt') {
19085
- return (React__default['default'].createElement(CameraDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19186
+ return (React__default['default'].createElement(CameraDomainPermissions, { appName: 'app',
19187
+ /* @conditional-compile-remove(unsupported-browser) */
19188
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19086
19189
  ? () => {
19087
19190
  onPermissionsTroubleshootingClick(permissionsState);
19088
19191
  }
@@ -19092,7 +19195,9 @@ const CallReadinessModal = (props) => {
19092
19195
  }
19093
19196
  // if video permission is set up but audio is not
19094
19197
  else if (audioState === 'prompt') {
19095
- return (React__default['default'].createElement(MicrophoneDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19198
+ return (React__default['default'].createElement(MicrophoneDomainPermissions, { appName: 'app',
19199
+ /* @conditional-compile-remove(unsupported-browser) */
19200
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19096
19201
  ? () => {
19097
19202
  onPermissionsTroubleshootingClick(permissionsState);
19098
19203
  }
@@ -19100,7 +19205,9 @@ const CallReadinessModal = (props) => {
19100
19205
  }
19101
19206
  // if both video and audio are denied
19102
19207
  else if (videoState === 'denied' && audioState === 'denied') {
19103
- return (React__default['default'].createElement(CameraAndMicrophoneDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19208
+ return (React__default['default'].createElement(CameraAndMicrophoneDomainPermissions, { appName: 'app',
19209
+ /* @conditional-compile-remove(unsupported-browser) */
19210
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19104
19211
  ? () => {
19105
19212
  onPermissionsTroubleshootingClick(permissionsState);
19106
19213
  }
@@ -19108,7 +19215,9 @@ const CallReadinessModal = (props) => {
19108
19215
  }
19109
19216
  // if only video is denied
19110
19217
  else if (videoState === 'denied') {
19111
- return (React__default['default'].createElement(CameraDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19218
+ return (React__default['default'].createElement(CameraDomainPermissions, { appName: 'app',
19219
+ /* @conditional-compile-remove(unsupported-browser) */
19220
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19112
19221
  ? () => {
19113
19222
  onPermissionsTroubleshootingClick(permissionsState);
19114
19223
  }
@@ -19118,7 +19227,9 @@ const CallReadinessModal = (props) => {
19118
19227
  }
19119
19228
  // if only audio is denied
19120
19229
  else {
19121
- return (React__default['default'].createElement(MicrophoneDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19230
+ return (React__default['default'].createElement(MicrophoneDomainPermissions, { appName: 'app',
19231
+ /* @conditional-compile-remove(unsupported-browser) */
19232
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19122
19233
  ? () => {
19123
19234
  onPermissionsTroubleshootingClick(permissionsState);
19124
19235
  }
@@ -19144,26 +19255,35 @@ const CallReadinessModal = (props) => {
19144
19255
  * @private
19145
19256
  */
19146
19257
  const CallReadinessModalFallBack = (props) => {
19147
- const { mobileView, cameraPermissionGranted, microphonePermissionGranted, checkPermissionModalShowing, permissionsState, isPermissionsModalDismissed, setIsPermissionsModalDismissed, onPermissionsTroubleshootingClick } = props;
19258
+ const { mobileView, checkPermissionModalShowing, permissionsState,
19259
+ /* @conditional-compile-remove(unsupported-browser) */ environmentInfo, isPermissionsModalDismissed, setIsPermissionsModalDismissed, onPermissionsTroubleshootingClick } = props;
19148
19260
  const onLightDismissTriggered = () => {
19149
19261
  // do nothing here
19150
19262
  // only way to dismiss this drawer is clicking on allow access which will leads to device permission prompt
19151
19263
  };
19152
- // When permissions are not set, value is undefined, do nothing here
19153
- // When permissions are set to denied, value is false, show helper screen
19154
- const showModal = cameraPermissionGranted === false || microphonePermissionGranted === false;
19264
+ const videoState = permissionsState.camera;
19265
+ const audioState = permissionsState.microphone;
19266
+ // When permissions are not set, do nothing here
19267
+ // When permissions are set to denied, show helper screen
19268
+ const showModal = videoState === 'denied' || audioState === 'denied';
19269
+ /* @conditional-compile-remove(unsupported-browser) */
19270
+ const isSafari = _isSafari(environmentInfo);
19155
19271
  const modal = !showModal
19156
19272
  ? undefined
19157
19273
  : () => {
19158
- if (cameraPermissionGranted === false && microphonePermissionGranted === false) {
19159
- return (React__default['default'].createElement(CameraAndMicrophoneDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19274
+ if (videoState === 'denied' && audioState === 'denied') {
19275
+ return (React__default['default'].createElement(CameraAndMicrophoneDomainPermissions, { appName: 'app',
19276
+ /* @conditional-compile-remove(unsupported-browser) */
19277
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19160
19278
  ? () => {
19161
19279
  onPermissionsTroubleshootingClick(permissionsState);
19162
19280
  }
19163
19281
  : undefined, type: "denied" }));
19164
19282
  }
19165
- else if (cameraPermissionGranted === false && microphonePermissionGranted) {
19166
- return (React__default['default'].createElement(CameraDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19283
+ else if (videoState === 'denied' && audioState === 'granted') {
19284
+ return (React__default['default'].createElement(CameraDomainPermissions, { appName: 'app',
19285
+ /* @conditional-compile-remove(unsupported-browser) */
19286
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19167
19287
  ? () => {
19168
19288
  onPermissionsTroubleshootingClick(permissionsState);
19169
19289
  }
@@ -19172,7 +19292,9 @@ const CallReadinessModalFallBack = (props) => {
19172
19292
  }, type: "denied" }));
19173
19293
  }
19174
19294
  else {
19175
- return (React__default['default'].createElement(MicrophoneDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19295
+ return (React__default['default'].createElement(MicrophoneDomainPermissions, { appName: 'app',
19296
+ /* @conditional-compile-remove(unsupported-browser) */
19297
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19176
19298
  ? () => {
19177
19299
  onPermissionsTroubleshootingClick(permissionsState);
19178
19300
  }
@@ -19181,10 +19303,10 @@ const CallReadinessModalFallBack = (props) => {
19181
19303
  };
19182
19304
  if (mobileView) {
19183
19305
  return (React__default['default'].createElement(React__default['default'].Fragment, null,
19184
- (checkPermissionModalShowing ||
19185
- microphonePermissionGranted === undefined ||
19186
- cameraPermissionGranted === undefined) && (React__default['default'].createElement(_DrawerSurface, { onLightDismiss: onLightDismissTriggered, styles: drawerContainerStyles(DRAWER_HIGH_Z_BAND) },
19187
- React__default['default'].createElement(CameraAndMicrophoneDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19306
+ (checkPermissionModalShowing || audioState === 'prompt' || videoState === 'prompt') && (React__default['default'].createElement(_DrawerSurface, { onLightDismiss: onLightDismissTriggered, styles: drawerContainerStyles(DRAWER_HIGH_Z_BAND) },
19307
+ React__default['default'].createElement(CameraAndMicrophoneDomainPermissions, { appName: 'app',
19308
+ /* @conditional-compile-remove(unsupported-browser) */
19309
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19188
19310
  ? () => {
19189
19311
  onPermissionsTroubleshootingClick(permissionsState);
19190
19312
  }
@@ -19193,12 +19315,12 @@ const CallReadinessModalFallBack = (props) => {
19193
19315
  }
19194
19316
  else {
19195
19317
  return (React__default['default'].createElement(React__default['default'].Fragment, null,
19196
- (checkPermissionModalShowing ||
19197
- microphonePermissionGranted === undefined ||
19198
- cameraPermissionGranted === undefined) && (React__default['default'].createElement(react.Modal, { isOpen: isPermissionsModalDismissed, isBlocking: false, onDismiss: () => {
19318
+ (checkPermissionModalShowing || audioState === 'prompt' || videoState === 'prompt') && (React__default['default'].createElement(react.Modal, { isOpen: isPermissionsModalDismissed, isBlocking: false, onDismiss: () => {
19199
19319
  setIsPermissionsModalDismissed(false);
19200
19320
  }, overlay: { styles: { root: { background: 'rgba(0,0,0,0.9)' } } } },
19201
- React__default['default'].createElement(CameraAndMicrophoneDomainPermissions, { appName: 'app', onTroubleshootingClick: onPermissionsTroubleshootingClick
19321
+ React__default['default'].createElement(CameraAndMicrophoneDomainPermissions, { appName: 'app',
19322
+ /* @conditional-compile-remove(unsupported-browser) */
19323
+ browserHint: isSafari ? 'safari' : 'unset', onTroubleshootingClick: onPermissionsTroubleshootingClick
19202
19324
  ? () => {
19203
19325
  onPermissionsTroubleshootingClick(permissionsState);
19204
19326
  }
@@ -19233,13 +19355,15 @@ const ConfigurationPage = (props) => {
19233
19355
  let errorBarProps = usePropsFor$1(ErrorBar);
19234
19356
  const adapter = useAdapter();
19235
19357
  const deviceState = adapter.getState().devices;
19358
+ /* @conditional-compile-remove(unsupported-browser) */
19359
+ const environmentInfo = adapter.getState().environmentInfo;
19236
19360
  let disableStartCallButton = !microphonePermissionGranted || ((_a = deviceState.microphones) === null || _a === void 0 ? void 0 : _a.length) === 0;
19237
19361
  /* @conditional-compile-remove(rooms) */
19238
19362
  const rolePermissions = _usePermissions();
19239
19363
  /* @conditional-compile-remove(rooms) */
19240
19364
  // TODO: move this logic to the error bar selector once role is plumbed from the headless SDK
19241
19365
  if (!rolePermissions.cameraButton) {
19242
- errorBarProps = Object.assign(Object.assign({}, errorBarProps), { activeErrorMessages: errorBarProps.activeErrorMessages.filter((e) => e.type !== 'callCameraAccessDenied') });
19366
+ errorBarProps = Object.assign(Object.assign({}, errorBarProps), { activeErrorMessages: errorBarProps.activeErrorMessages.filter((e) => e.type !== 'callCameraAccessDenied' && e.type !== 'callCameraAccessDeniedSafari') });
19243
19367
  }
19244
19368
  /* @conditional-compile-remove(rooms) */
19245
19369
  if (!rolePermissions.microphoneButton) {
@@ -19267,8 +19391,24 @@ const ConfigurationPage = (props) => {
19267
19391
  /* @conditional-compile-remove(call-readiness) */
19268
19392
  const permissionsState = {
19269
19393
  // fall back to using cameraPermissionGranted and microphonePermissionGranted if permission API is not supported
19270
- camera: videoState && videoState !== 'unsupported' ? videoState : cameraPermissionGranted ? 'granted' : 'denied',
19271
- microphone: audioState && audioState !== 'unsupported' ? audioState : microphonePermissionGranted ? 'granted' : 'denied'
19394
+ camera: videoState && videoState !== 'unsupported'
19395
+ ? cameraPermissionGranted !== false
19396
+ ? videoState
19397
+ : 'denied'
19398
+ : cameraPermissionGranted !== false
19399
+ ? cameraPermissionGranted
19400
+ ? 'granted'
19401
+ : 'prompt'
19402
+ : 'denied',
19403
+ microphone: audioState && audioState !== 'unsupported'
19404
+ ? microphonePermissionGranted !== false
19405
+ ? audioState
19406
+ : 'denied'
19407
+ : microphonePermissionGranted !== false
19408
+ ? microphonePermissionGranted
19409
+ ? 'granted'
19410
+ : 'prompt'
19411
+ : 'denied'
19272
19412
  };
19273
19413
  /* @conditional-compile-remove(call-readiness) */
19274
19414
  const networkErrors = errorBarProps.activeErrorMessages.filter((message) => message.type === 'callNetworkQualityLow');
@@ -19307,13 +19447,17 @@ const ConfigurationPage = (props) => {
19307
19447
  videoState &&
19308
19448
  videoState !== 'unsupported' &&
19309
19449
  audioState &&
19310
- audioState !== 'unsupported' && (React__default['default'].createElement(CallReadinessModal, { mobileView: mobileView, audioState: audioState, videoState: videoState, permissionsState: permissionsState, isPermissionsModalDismissed: isPermissionsModalDismissed, setIsPermissionsModalDismissed: setIsPermissionsModalDismissed, onPermissionsTroubleshootingClick: onPermissionsTroubleshootingClick })),
19450
+ audioState !== 'unsupported' && (React__default['default'].createElement(CallReadinessModal, { mobileView: mobileView,
19451
+ /* @conditional-compile-remove(unsupported-browser) */
19452
+ environmentInfo: environmentInfo, permissionsState: permissionsState, isPermissionsModalDismissed: isPermissionsModalDismissed, setIsPermissionsModalDismissed: setIsPermissionsModalDismissed, onPermissionsTroubleshootingClick: onPermissionsTroubleshootingClick })),
19311
19453
  /* @conditional-compile-remove(call-readiness) */
19312
19454
  // show the following screen if permission API is not availible (unsupported) and videoState, audioState is assigned values
19313
19455
  callReadinessOptedIn &&
19314
19456
  videoState &&
19315
19457
  audioState &&
19316
- (videoState === 'unsupported' || audioState === 'unsupported') && (React__default['default'].createElement(CallReadinessModalFallBack, { mobileView: mobileView, cameraPermissionGranted: cameraPermissionGranted, microphonePermissionGranted: microphonePermissionGranted, checkPermissionModalShowing: forceShowingCheckPermissions, permissionsState: permissionsState, isPermissionsModalDismissed: isPermissionsModalDismissed, setIsPermissionsModalDismissed: setIsPermissionsModalDismissed, onPermissionsTroubleshootingClick: onPermissionsTroubleshootingClick })),
19458
+ (videoState === 'unsupported' || audioState === 'unsupported') && (React__default['default'].createElement(CallReadinessModalFallBack, { mobileView: mobileView, checkPermissionModalShowing: forceShowingCheckPermissions, permissionsState: permissionsState, isPermissionsModalDismissed: isPermissionsModalDismissed,
19459
+ /* @conditional-compile-remove(unsupported-browser) */
19460
+ environmentInfo: environmentInfo, setIsPermissionsModalDismissed: setIsPermissionsModalDismissed, onPermissionsTroubleshootingClick: onPermissionsTroubleshootingClick })),
19317
19461
  React__default['default'].createElement(react.Stack, { grow: true, horizontal: !mobileWithPreview, horizontalAlign: mobileWithPreview ? 'stretch' : 'center', verticalAlign: "center", tokens: mobileWithPreview ? configurationStackTokensMobile : configurationStackTokensDesktop },
19318
19462
  mobileWithPreview && (React__default['default'].createElement(react.Stack.Item, null,
19319
19463
  title,
@@ -20603,6 +20747,9 @@ class AzureCommunicationCallAdapter {
20603
20747
  const createAzureCommunicationCallAdapter = ({ userId, displayName, credential, locator,
20604
20748
  /* @conditional-compile-remove(PSTN-calls) */ alternateCallerId,
20605
20749
  /* @conditional-compile-remove(rooms) */ options }) => __awaiter$4(void 0, void 0, void 0, function* () {
20750
+ if (!isValidIdentifier(userId)) {
20751
+ throw new Error('Invalid identifier. Please provide valid identifier object.');
20752
+ }
20606
20753
  const callClient = createStatefulCallClient({
20607
20754
  userId,
20608
20755
  /* @conditional-compile-remove(PSTN-calls) */ alternateCallerId