fix(audio): improve help modal for listen only scenarios

The audio troubleshooting modal has very microphone-specific strings,
which might confuse users trying to join listen only.

Review the Help screen so that listen only scenarios are more generic.
As a bonus, review the unknownError locale with a more actionable text.
This commit is contained in:
prlanzarin 2024-04-16 14:33:23 -03:00
parent f91402bc4a
commit 9956af9aa1
4 changed files with 55 additions and 30 deletions

View File

@ -30,6 +30,7 @@ const propTypes = {
isConnecting: PropTypes.bool.isRequired, isConnecting: PropTypes.bool.isRequired,
isConnected: PropTypes.bool.isRequired, isConnected: PropTypes.bool.isRequired,
isUsingAudio: PropTypes.bool.isRequired, isUsingAudio: PropTypes.bool.isRequired,
isListenOnly: PropTypes.bool.isRequired,
inputDeviceId: PropTypes.string, inputDeviceId: PropTypes.string,
outputDeviceId: PropTypes.string, outputDeviceId: PropTypes.string,
formattedDialNum: PropTypes.string.isRequired, formattedDialNum: PropTypes.string.isRequired,
@ -131,8 +132,7 @@ class AudioModal extends Component {
this.state = { this.state = {
content: null, content: null,
hasError: false, hasError: false,
errCode: null, errorInfo: null,
errMessage: null,
}; };
this.handleGoToAudioOptions = this.handleGoToAudioOptions.bind(this); this.handleGoToAudioOptions = this.handleGoToAudioOptions.bind(this);
@ -235,6 +235,7 @@ class AudioModal extends Component {
this.setState({ this.setState({
hasError: false, hasError: false,
content: null, content: null,
errorInfo: null,
}); });
return this.handleGoToEchoTest(); return this.handleGoToEchoTest();
@ -258,8 +259,10 @@ class AudioModal extends Component {
if (noSSL) { if (noSSL) {
return this.setState({ return this.setState({
content: 'help', content: 'help',
errorInfo: {
errCode: MIC_ERROR.NO_SSL, errCode: MIC_ERROR.NO_SSL,
errMessage: 'NoSSL', errMessage: 'NoSSL',
},
}); });
} }
@ -280,6 +283,7 @@ class AudioModal extends Component {
this.setState({ this.setState({
hasError: false, hasError: false,
disableActions: true, disableActions: true,
errorInfo: null,
}); });
return joinEchoTest().then(() => { return joinEchoTest().then(() => {
@ -288,7 +292,7 @@ class AudioModal extends Component {
disableActions: false, disableActions: false,
}); });
}).catch((err) => { }).catch((err) => {
this.handleJoinMicrophoneError(err); this.handleJoinAudioError(err);
}); });
} }
@ -306,6 +310,8 @@ class AudioModal extends Component {
this.setState({ this.setState({
disableActions: true, disableActions: true,
hasError: false,
errorInfo: null,
}); });
return joinListenOnly().then(() => { return joinListenOnly().then(() => {
@ -313,11 +319,7 @@ class AudioModal extends Component {
disableActions: false, disableActions: false,
}); });
}).catch((err) => { }).catch((err) => {
if (err.type === 'MEDIA_ERROR') { this.handleJoinAudioError(err);
this.setState({
content: 'help',
});
}
}); });
} }
@ -347,6 +349,7 @@ class AudioModal extends Component {
this.setState({ this.setState({
hasError: false, hasError: false,
disableActions: true, disableActions: true,
errorInfo: null,
}); });
joinMicrophone().then(() => { joinMicrophone().then(() => {
@ -354,28 +357,32 @@ class AudioModal extends Component {
disableActions: false, disableActions: false,
}); });
}).catch((err) => { }).catch((err) => {
this.handleJoinMicrophoneError(err); this.handleJoinAudioError(err);
}); });
} }
handleJoinMicrophoneError(err) { handleJoinAudioError(err) {
const { type, errCode, errMessage } = err; const { type, errCode, errMessage } = err;
switch (type) { switch (type) {
case 'MEDIA_ERROR': case 'MEDIA_ERROR':
this.setState({ this.setState({
content: 'help', content: 'help',
disableActions: false,
errorInfo: {
errCode, errCode,
errMessage, errMessage,
disableActions: false, }
}); });
break; break;
case 'CONNECTION_ERROR': case 'CONNECTION_ERROR':
default: default:
this.setState({ this.setState({
disableActions: false,
errorInfo: {
errCode, errCode,
errMessage: type, errMessage: type,
disableActions: false, },
}); });
break; break;
} }
@ -533,9 +540,11 @@ class AudioModal extends Component {
: 0 : 0
this.setState({ this.setState({
content: 'help', content: 'help',
disableActions: false,
errorInfo: {
errCode, errCode,
errMessage: error?.name || 'NotAllowedError', errMessage: error?.name || 'NotAllowedError',
disableActions: false, },
}); });
}; };
@ -561,20 +570,21 @@ class AudioModal extends Component {
} }
renderHelp() { renderHelp() {
const { errCode, errMessage } = this.state; const { errorInfo } = this.state;
const { AudioError, getTroubleshootingLink } = this.props; const { AudioError, getTroubleshootingLink, isListenOnly } = this.props;
const audioErr = { const audioErr = {
...AudioError, ...AudioError,
code: errCode, code: errorInfo?.errCode,
message: errMessage, message: errorInfo?.errMessage,
}; };
return ( return (
<Help <Help
handleBack={this.handleGoToAudioOptions} handleBack={this.handleGoToAudioOptions}
audioErr={audioErr} audioErr={audioErr}
troubleshootingLink={getTroubleshootingLink(errCode)} isListenOnly={isListenOnly}
troubleshootingLink={getTroubleshootingLink(errorInfo?.errCode)}
/> />
); );
} }

View File

@ -100,5 +100,6 @@ export default lockContextContainer(withTracker(({ userLocks, setIsOpen }) => {
isRTL, isRTL,
AudioError, AudioError,
getTroubleshootingLink: AudioModalService.getTroubleshootingLink, getTroubleshootingLink: AudioModalService.getTroubleshootingLink,
isListenOnly: Service.isListenOnly(),
}); });
})(AudioModalContainer)); })(AudioModalContainer));

View File

@ -7,6 +7,7 @@ const propTypes = {
intl: PropTypes.shape({ intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired, formatMessage: PropTypes.func.isRequired,
}).isRequired, }).isRequired,
isListenOnly: PropTypes.bool.isRequired,
audioErr: PropTypes.shape({ audioErr: PropTypes.shape({
code: PropTypes.number, code: PropTypes.number,
message: PropTypes.string, message: PropTypes.string,
@ -25,9 +26,13 @@ const defaultProps = {
}; };
const intlMessages = defineMessages({ const intlMessages = defineMessages({
helpSubtitle: { helpSubtitleMic: {
id: 'app.audioModal.helpSubtitle', id: 'app.audioModal.helpSubtitleMic',
description: 'Text description for the audio help subtitle', description: 'Text description for the audio help subtitle (microphones)',
},
helpSubtitleGeneric: {
id: 'app.audioModal.helpSubtitleGeneric',
description: 'Text description for the audio help subtitle (generic)',
}, },
helpPermissionStep1: { helpPermissionStep1: {
id: 'app.audioModal.helpPermissionStep1', id: 'app.audioModal.helpPermissionStep1',
@ -68,6 +73,14 @@ const intlMessages = defineMessages({
}); });
class Help extends Component { class Help extends Component {
getSubtitle() {
const { intl, isListenOnly } = this.props;
return !isListenOnly
? intl.formatMessage(intlMessages.helpSubtitleMic)
: intl.formatMessage(intlMessages.helpSubtitleGeneric);
}
renderNoSSL() { renderNoSSL() {
const { intl } = this.props; const { intl } = this.props;
@ -93,7 +106,7 @@ class Help extends Component {
return ( return (
<> <>
<Styled.Text> <Styled.Text>
{intl.formatMessage(intlMessages.helpSubtitle)} {this.getSubtitle()}
</Styled.Text> </Styled.Text>
<Styled.PermissionHelpSteps> <Styled.PermissionHelpSteps>
<li>{intl.formatMessage(intlMessages.helpPermissionStep1)}</li> <li>{intl.formatMessage(intlMessages.helpPermissionStep1)}</li>
@ -111,7 +124,7 @@ class Help extends Component {
return ( return (
<> <>
<Styled.Text> <Styled.Text>
{intl.formatMessage(intlMessages.helpSubtitle)} {this.getSubtitle()}
</Styled.Text> </Styled.Text>
<Styled.Text> <Styled.Text>
{intl.formatMessage(intlMessages.unknownError)} {intl.formatMessage(intlMessages.unknownError)}

View File

@ -733,12 +733,13 @@
"app.audioModal.echoTestTitle": "This is a private echo test. Speak a few words. Did you hear audio?", "app.audioModal.echoTestTitle": "This is a private echo test. Speak a few words. Did you hear audio?",
"app.audioModal.settingsTitle": "Change your audio settings", "app.audioModal.settingsTitle": "Change your audio settings",
"app.audioModal.helpTitle": "There was an issue with your audio devices", "app.audioModal.helpTitle": "There was an issue with your audio devices",
"app.audioModal.helpSubtitle": "We couldn't enable your microphone", "app.audioModal.helpSubtitleMic": "We couldn't enable your microphone",
"app.audioModal.helpSubtitleGeneric": "We're having trouble establishing an audio connection",
"app.audioModal.helpPermissionStep1": "When joining a call, accept all requests if prompted to use your microphone.", "app.audioModal.helpPermissionStep1": "When joining a call, accept all requests if prompted to use your microphone.",
"app.audioModal.helpPermissionStep2": "Check browser and device settings to ensure microphone access is allowed.", "app.audioModal.helpPermissionStep2": "Check browser and device settings to ensure microphone access is allowed.",
"app.audioModal.helpPermissionStep3": "Refresh the page and try again.", "app.audioModal.helpPermissionStep3": "Refresh the page and try again.",
"app.audioModal.help.troubleshoot": "Still having issues? Click here for help.", "app.audioModal.help.troubleshoot": "Still having issues? Click here for help.",
"app.audioModal.help.unknownError": "Unknown error. Review your browser and system settings and try again.", "app.audioModal.help.unknownError": "Review your browser and system settings. Restart your browser and try again.",
"app.audioModal.help.errorCode": "Error code: {0} - {1}", "app.audioModal.help.errorCode": "Error code: {0} - {1}",
"app.audioModal.help.noSSL": "This page is unsecured. For microphone access to be allowed the page must be served over HTTPS. Please contact the server administrator.", "app.audioModal.help.noSSL": "This page is unsecured. For microphone access to be allowed the page must be served over HTTPS. Please contact the server administrator.",
"app.audioModal.help.macNotAllowed": "It looks like your Mac System Preferences are blocking access to your microphone. Open System Preferences > Security & Privacy > Privacy > Microphone, and verify that the browser you're using is checked.", "app.audioModal.help.macNotAllowed": "It looks like your Mac System Preferences are blocking access to your microphone. Open System Preferences > Security & Privacy > Privacy > Microphone, and verify that the browser you're using is checked.",