UNPKG

communication-react-19

Version:

React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)

247 lines 14.1 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import { getAssignedBreakoutRoom, getDeviceManager, getDiagnostics, getLatestErrors, getEnvironmentInfo, getCallState } from './baseSelectors'; import { getLatestNotifications } from './baseSelectors'; import { getMeetingConferencePhones } from './baseSelectors'; import { createSelector } from 'reselect'; import { DiagnosticQuality } from '@azure/communication-calling'; /** * Select the active errors from the state for the `Notification` component. * * Invariants: * - `ErrorType` is never repeated in the returned errors. * - Errors are returned in a fixed order by `ErrorType`. * * @public */ export const notificationStackSelector = createSelector([ getLatestErrors, getLatestNotifications, getDiagnostics, getDeviceManager, getCallState, getEnvironmentInfo, getMeetingConferencePhones, getAssignedBreakoutRoom ], (latestErrors, latestNotifications, diagnostics, deviceManager, callStatus, environmentInfo, meetingConference, assignedBreakoutRoom) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u; // The order in which the errors are returned is significant: The `Notification` shows errors on the UI in that order. // There are several options for the ordering: // - Sorted by when the errors happened (latest first / oldest first). // - Stable sort by error type. // // 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 // have timestamps for errors. const activeErrorMessages = []; const isSafari = () => { return (environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.environment.browser) === 'safari'; }; const isMacOS = () => { return (environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.environment.platform) === 'mac'; }; // Errors reported via diagnostics are more reliable than from API method failures, so process those first. let isTeamsMeetingWithPhones = false; if (meetingConference && meetingConference.length > 0) { isTeamsMeetingWithPhones = true; } if (((_a = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.network.latest.networkReceiveQuality) === null || _a === void 0 ? void 0 : _a.value) === DiagnosticQuality.Bad || ((_b = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.network.latest.networkReceiveQuality) === null || _b === void 0 ? void 0 : _b.value) === DiagnosticQuality.Poor) { if (isTeamsMeetingWithPhones) { activeErrorMessages.push({ type: 'teamsMeetingCallNetworkQualityLow' }); } else { activeErrorMessages.push({ type: 'callNetworkQualityLow' }); } } if (((_c = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.noSpeakerDevicesEnumerated) === null || _c === void 0 ? void 0 : _c.value) === true) { activeErrorMessages.push({ type: 'callNoSpeakerFound' }); } if (((_d = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.noMicrophoneDevicesEnumerated) === null || _d === void 0 ? void 0 : _d.value) === true) { activeErrorMessages.push({ type: 'callNoMicrophoneFound' }); } if (((_e = deviceManager.deviceAccess) === null || _e === void 0 ? void 0 : _e.audio) === false && isSafari()) { activeErrorMessages.push({ type: 'callMicrophoneAccessDeniedSafari' }); } if (((_f = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.microphonePermissionDenied) === null || _f === void 0 ? void 0 : _f.value) === true && isMacOS()) { activeErrorMessages.push({ type: 'callMacOsMicrophoneAccessDenied' }); } else if ((((_g = deviceManager.deviceAccess) === null || _g === void 0 ? void 0 : _g.audio) === false && !isSafari()) || (((_h = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.microphonePermissionDenied) === null || _h === void 0 ? void 0 : _h.value) === true && !isMacOS())) { activeErrorMessages.push({ type: 'callMicrophoneAccessDenied' }); } const microphoneMuteUnexpectedlyDiagnostic = (diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.microphoneMuteUnexpectedly) || (diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.microphoneNotFunctioning); if (microphoneMuteUnexpectedlyDiagnostic) { if (microphoneMuteUnexpectedlyDiagnostic.value === DiagnosticQuality.Bad) { // Inform the user that microphone stopped working and inform them to start microphone again activeErrorMessages.push({ type: 'callMicrophoneMutedBySystem' }); } else if (microphoneMuteUnexpectedlyDiagnostic.value === DiagnosticQuality.Good) { // Inform the user that microphone recovered activeErrorMessages.push({ type: 'callMicrophoneUnmutedBySystem' }); } } const cameraStoppedUnexpectedlyDiagnostic = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.cameraStoppedUnexpectedly; if (cameraStoppedUnexpectedlyDiagnostic) { if (cameraStoppedUnexpectedlyDiagnostic.value === DiagnosticQuality.Bad) { // Inform the user that camera stopped working and inform them to start video again activeErrorMessages.push({ type: 'callVideoStoppedBySystem' }); } else if (cameraStoppedUnexpectedlyDiagnostic.value === DiagnosticQuality.Good) { // Inform the user that camera recovered activeErrorMessages.push({ type: 'callVideoRecoveredBySystem' }); } } if (((_j = deviceManager.deviceAccess) === null || _j === void 0 ? void 0 : _j.video) === false && isSafari()) { activeErrorMessages.push({ type: 'callCameraAccessDeniedSafari' }); } else if (((_k = deviceManager.deviceAccess) === null || _k === void 0 ? void 0 : _k.video) === false) { activeErrorMessages.push({ type: 'callCameraAccessDenied' }); } else { if (((_l = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.cameraFreeze) === null || _l === void 0 ? void 0 : _l.value) === true) { activeErrorMessages.push({ type: 'cameraFrozenForRemoteParticipants' }); } } /** * show the Mac specific strings if the platform is detected as mac */ if (((_m = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.cameraPermissionDenied) === null || _m === void 0 ? void 0 : _m.value) === true && isMacOS()) { activeErrorMessages.push({ type: 'callMacOsCameraAccessDenied' }); } /** * This UFD only works on mac still so we should only see it fire on mac. */ if (((_o = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.screenshareRecordingDisabled) === null || _o === void 0 ? void 0 : _o.value) === true && isMacOS()) { activeErrorMessages.push({ type: 'callMacOsScreenShareAccessDenied' }); } else if (((_p = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.screenshareRecordingDisabled) === null || _p === void 0 ? void 0 : _p.value) === true) { activeErrorMessages.push({ type: 'startScreenShareGeneric' }); } // Prefer to show errors with privacy implications. appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.stopVideo', 'stopVideoGeneric'); appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.mute', 'muteGeneric'); appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.stopScreenSharing', 'stopScreenShareGeneric'); if (((_q = latestErrors['Call.startVideo']) === null || _q === void 0 ? void 0 : _q.message) === 'Call.startVideo: Video operation failure SourceUnavailableError') { appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.startVideo', 'callCameraAlreadyInUse'); } else if (((_r = latestErrors['Call.startVideo']) === null || _r === void 0 ? void 0 : _r.message) === 'Call.startVideo: Video operation failure permissionDeniedError') { appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.startVideo', 'callCameraAccessDenied'); } else { appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.startVideo', 'startVideoGeneric'); } appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.unmute', 'unmuteGeneric'); if (latestNotifications && !latestNotifications['capabilityUnmuteMicAbsent'] && !latestNotifications['capabilityUnmuteMicPresent']) { appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.mutedByOthers', 'mutedByRemoteParticipant'); } appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'VideoEffectsFeature.startEffects', 'unableToStartVideoEffect'); if (((_s = latestErrors['CallAgent.join']) === null || _s === void 0 ? void 0 : _s.message) === 'CallAgent.join: Invalid meeting link') { appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'CallAgent.join', 'failedToJoinCallInvalidMeetingLink'); } else { appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'CallAgent.join', 'failedToJoinCallGeneric'); } if ((_t = latestErrors['Call.feature']) === null || _t === void 0 ? void 0 : _t.message.match(/Call\.feature: startSpotlight failed\. \d+ is the max number of participants that can be Spotlighted/g)) { appendActiveErrorIfDefined(activeErrorMessages, latestErrors, 'Call.feature', 'startSpotlightWhileMaxParticipantsAreSpotlighted'); } //below is for active notifications const activeNotifications = []; if (((_u = diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.media.latest.speakingWhileMicrophoneIsMuted) === null || _u === void 0 ? void 0 : _u.value) && // only show this notification when the participant is in an active call and not on screens such as Lobby callStatus === 'Connected') { activeNotifications.push({ type: 'speakingWhileMuted', timestamp: new Date(Date.now()), autoDismiss: true, ariaLive: 'off' // "You're muted" is too noisy, so we don't want to announce it. }); } if (latestNotifications['assignedBreakoutRoomOpened']) { activeNotifications.push({ type: 'assignedBreakoutRoomOpened', timestamp: latestNotifications['assignedBreakoutRoomOpened'].timestamp }); } if (latestNotifications['assignedBreakoutRoomOpenedPromptJoin'] && assignedBreakoutRoom) { activeNotifications.push({ type: 'assignedBreakoutRoomOpenedPromptJoin', timestamp: latestNotifications['assignedBreakoutRoomOpenedPromptJoin'].timestamp, onClickPrimaryButton: () => assignedBreakoutRoom.join() }); } if (latestNotifications['assignedBreakoutRoomChanged']) { activeNotifications.push({ type: 'assignedBreakoutRoomChanged', timestamp: latestNotifications['assignedBreakoutRoomChanged'].timestamp }); } if (latestNotifications['assignedBreakoutRoomClosed']) { activeNotifications.push({ type: 'assignedBreakoutRoomClosed', timestamp: latestNotifications['assignedBreakoutRoomClosed'].timestamp }); } if (latestNotifications['breakoutRoomJoined']) { activeNotifications.push({ type: 'breakoutRoomJoined', timestamp: latestNotifications['breakoutRoomJoined'].timestamp }); } if (latestNotifications['breakoutRoomClosingSoon']) { activeNotifications.push({ type: 'breakoutRoomClosingSoon', timestamp: latestNotifications['breakoutRoomClosingSoon'].timestamp }); } if (latestNotifications['capabilityTurnVideoOnPresent']) { activeNotifications.push({ type: 'capabilityTurnVideoOnPresent', timestamp: latestNotifications['capabilityTurnVideoOnPresent'].timestamp }); } if (latestNotifications['capabilityTurnVideoOnAbsent']) { activeNotifications.push({ type: 'capabilityTurnVideoOnAbsent', timestamp: latestNotifications['capabilityTurnVideoOnAbsent'].timestamp }); } if (latestNotifications['capabilityUnmuteMicPresent']) { activeNotifications.push({ type: 'capabilityUnmuteMicPresent', timestamp: latestNotifications['capabilityUnmuteMicPresent'].timestamp }); } if (latestNotifications['capabilityUnmuteMicAbsent']) { activeNotifications.push({ type: 'capabilityUnmuteMicAbsent', timestamp: latestNotifications['capabilityUnmuteMicAbsent'].timestamp }); } if (latestNotifications['togetherModeStarted']) { activeNotifications.push({ type: 'togetherModeStarted', timestamp: latestNotifications['togetherModeStarted'].timestamp, autoDismiss: true }); } if (latestNotifications['togetherModeEnded']) { activeNotifications.push({ type: 'togetherModeEnded', timestamp: latestNotifications['togetherModeEnded'].timestamp, autoDismiss: true }); } return { activeErrorMessages: activeErrorMessages, activeNotifications: activeNotifications }; }); const appendActiveErrorIfDefined = (activeErrorMessages, latestErrors, target, activeErrorType) => { if (latestErrors[target] === undefined) { return; } activeErrorMessages.push({ type: activeErrorType, timestamp: latestErrors[target].timestamp }); }; //# sourceMappingURL=notificationStackSelector.js.map