diff --git a/change-beta/@azure-communication-react-7ce0977d-2176-4487-b23c-32fba99ce997.json b/change-beta/@azure-communication-react-7ce0977d-2176-4487-b23c-32fba99ce997.json new file mode 100644 index 00000000000..61fd7be2aff --- /dev/null +++ b/change-beta/@azure-communication-react-7ce0977d-2176-4487-b23c-32fba99ce997.json @@ -0,0 +1,9 @@ +{ + "type": "prerelease", + "area": "feature", + "workstream": "Allow join without mic", + "comment": "Add composite option to allow join without microphone access", + "packageName": "@azure/communication-react", + "email": "96077406+carocao-msft@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/communication-react/review/beta/communication-react.api.md b/packages/communication-react/review/beta/communication-react.api.md index 1bb6fe51d21..f0007e96733 100644 --- a/packages/communication-react/review/beta/communication-react.api.md +++ b/packages/communication-react/review/beta/communication-react.api.md @@ -799,6 +799,9 @@ export type CallCompositeOptions = { spotlight?: { hideSpotlightButtons?: boolean; }; + joinCallOptions?: { + microphoneCheck?: 'requireMicrophoneAvailable' | 'skip'; + }; }; // @public @@ -1641,6 +1644,9 @@ export type CallWithChatCompositeOptions = { hideSpotlightButtons?: boolean; }; richTextEditor?: boolean; + joinCallOptions?: { + microphoneCheck?: 'requireMicrophoneAvailable' | 'skip'; + }; }; // @public diff --git a/packages/communication-react/review/stable/communication-react.api.md b/packages/communication-react/review/stable/communication-react.api.md index 7673063b760..b69f6aded54 100644 --- a/packages/communication-react/review/stable/communication-react.api.md +++ b/packages/communication-react/review/stable/communication-react.api.md @@ -632,6 +632,9 @@ export type CallCompositeOptions = { spotlight?: { hideSpotlightButtons?: boolean; }; + joinCallOptions?: { + microphoneCheck?: 'requireMicrophoneAvailable' | 'skip'; + }; }; // @public @@ -1407,6 +1410,9 @@ export type CallWithChatCompositeOptions = { spotlight?: { hideSpotlightButtons?: boolean; }; + joinCallOptions?: { + microphoneCheck?: 'requireMicrophoneAvailable' | 'skip'; + }; }; // @public diff --git a/packages/react-composites/src/composites/CallComposite/CallComposite.tsx b/packages/react-composites/src/composites/CallComposite/CallComposite.tsx index 573e7e5428f..06e3c178059 100644 --- a/packages/react-composites/src/composites/CallComposite/CallComposite.tsx +++ b/packages/react-composites/src/composites/CallComposite/CallComposite.tsx @@ -349,6 +349,18 @@ export type CallCompositeOptions = { */ hideSpotlightButtons?: boolean; }; + /** + * Options for settings related to joining a call. + */ + joinCallOptions?: { + /** + * options for checking microphone permissions when joining a call. + * block on access will block the user from joining the call if the microphone permission is not granted. + * skip will allow the user to join the call without granting the microphone permission. + * @defaultValue 'requireMicrophoneAvailable' + */ + microphoneCheck?: 'requireMicrophoneAvailable' | 'skip'; + }; }; type MainScreenProps = { @@ -556,6 +568,7 @@ const MainScreen = (props: MainScreenProps): JSX.Element => { case 'configuration': pageElement = ( { if (callees) { diff --git a/packages/react-composites/src/composites/CallComposite/pages/ConfigurationPage.tsx b/packages/react-composites/src/composites/CallComposite/pages/ConfigurationPage.tsx index 2b5b209a659..0a1e6a0a778 100644 --- a/packages/react-composites/src/composites/CallComposite/pages/ConfigurationPage.tsx +++ b/packages/react-composites/src/composites/CallComposite/pages/ConfigurationPage.tsx @@ -103,6 +103,18 @@ export interface ConfigurationPageProps { backgroundImage?: { url: string; }; + /** + * Options for settings related to joining a call. + */ + joinCallOptions?: { + /** + * options for checking microphone permissions when joining a call. + * block on access will block the user from joining the call if the microphone permission is not granted. + * skip will allow the user to join the call without granting the microphone permission. + * @defaultValue 'requireMicrophoneAvailable' + */ + microphoneCheck?: 'requireMicrophoneAvailable' | 'skip'; + }; } /** @@ -115,7 +127,8 @@ export const ConfigurationPage = (props: ConfigurationPageProps): JSX.Element => modalLayerHostId, /* @conditional-compile-remove(call-readiness) */ deviceChecks, /* @conditional-compile-remove(call-readiness) */ onPermissionsTroubleshootingClick, - /* @conditional-compile-remove(call-readiness) */ onNetworkingTroubleShootingClick + /* @conditional-compile-remove(call-readiness) */ onNetworkingTroubleShootingClick, + joinCallOptions = { microphoneCheck: 'requireMicrophoneAvailable' } } = props; const theme = useTheme(); @@ -144,7 +157,9 @@ export const ConfigurationPage = (props: ConfigurationPageProps): JSX.Element => const microphones = useSelector(getMicrophones); const environmentInfo = useSelector(getEnvironmentInfo); - let disableStartCallButton = !microphonePermissionGranted || microphones?.length === 0; + let disableStartCallButton = + (!microphonePermissionGranted || microphones?.length === 0) && + joinCallOptions.microphoneCheck === 'requireMicrophoneAvailable'; const role = useSelector(getRole); const isCameraOn = useSelector(localVideoSelector).isAvailable; diff --git a/packages/react-composites/src/composites/CallWithChatComposite/CallWithChatComposite.tsx b/packages/react-composites/src/composites/CallWithChatComposite/CallWithChatComposite.tsx index 81288658b60..000e758bdca 100644 --- a/packages/react-composites/src/composites/CallWithChatComposite/CallWithChatComposite.tsx +++ b/packages/react-composites/src/composites/CallWithChatComposite/CallWithChatComposite.tsx @@ -281,6 +281,18 @@ export type CallWithChatCompositeOptions = { * @beta */ richTextEditor?: boolean; + /** + * Options for settings related to joining a call. + */ + joinCallOptions?: { + /** + * options for checking microphone permissions when joining a call. + * block on access will block the user from joining the call if the microphone permission is not granted. + * skip will allow the user to join the call without granting the microphone permission. + * @defaultValue 'requireMicrophoneAvailable' + */ + microphoneCheck?: 'requireMicrophoneAvailable' | 'skip'; + }; }; type CallWithChatScreenProps = { @@ -360,6 +372,18 @@ type CallWithChatScreenProps = { }; /* @conditional-compile-remove(rich-text-editor-composite-support) */ richTextEditor?: boolean; + /** + * Options for settings related to joining a call. + */ + joinCallOptions?: { + /** + * options for checking microphone permissions when joining a call. + * block on access will block the user from joining the call if the microphone permission is not granted. + * skip will allow the user to join the call without granting the microphone permission. + * @defaultValue 'requireMicrophoneAvailable' + */ + microphoneCheck?: 'requireMicrophoneAvailable' | 'skip'; + }; }; const CallWithChatScreen = (props: CallWithChatScreenProps): JSX.Element => { @@ -539,7 +563,8 @@ const CallWithChatScreen = (props: CallWithChatScreenProps): JSX.Element => { logo: props.logo, backgroundImage: props.backgroundImage }, - spotlight: props.spotlight + spotlight: props.spotlight, + joinCallOptions: props.joinCallOptions }), [ props.callControls, @@ -561,7 +586,8 @@ const CallWithChatScreen = (props: CallWithChatScreenProps): JSX.Element => { surveyOptions, props.logo, props.backgroundImage, - props.spotlight + props.spotlight, + props.joinCallOptions ] ); @@ -733,6 +759,7 @@ export const CallWithChatComposite = (props: CallWithChatCompositeProps): JSX.El spotlight={options?.spotlight} /* @conditional-compile-remove(rich-text-editor-composite-support) */ richTextEditor={options?.richTextEditor} + joinCallOptions={options?.joinCallOptions} /> );