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

View File

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

View File

@ -7,6 +7,7 @@ const propTypes = {
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
isListenOnly: PropTypes.bool.isRequired,
audioErr: PropTypes.shape({
code: PropTypes.number,
message: PropTypes.string,
@ -25,9 +26,13 @@ const defaultProps = {
};
const intlMessages = defineMessages({
helpSubtitle: {
id: 'app.audioModal.helpSubtitle',
description: 'Text description for the audio help subtitle',
helpSubtitleMic: {
id: 'app.audioModal.helpSubtitleMic',
description: 'Text description for the audio help subtitle (microphones)',
},
helpSubtitleGeneric: {
id: 'app.audioModal.helpSubtitleGeneric',
description: 'Text description for the audio help subtitle (generic)',
},
helpPermissionStep1: {
id: 'app.audioModal.helpPermissionStep1',
@ -68,6 +73,14 @@ const intlMessages = defineMessages({
});
class Help extends Component {
getSubtitle() {
const { intl, isListenOnly } = this.props;
return !isListenOnly
? intl.formatMessage(intlMessages.helpSubtitleMic)
: intl.formatMessage(intlMessages.helpSubtitleGeneric);
}
renderNoSSL() {
const { intl } = this.props;
@ -93,7 +106,7 @@ class Help extends Component {
return (
<>
<Styled.Text>
{intl.formatMessage(intlMessages.helpSubtitle)}
{this.getSubtitle()}
</Styled.Text>
<Styled.PermissionHelpSteps>
<li>{intl.formatMessage(intlMessages.helpPermissionStep1)}</li>
@ -111,7 +124,7 @@ class Help extends Component {
return (
<>
<Styled.Text>
{intl.formatMessage(intlMessages.helpSubtitle)}
{this.getSubtitle()}
</Styled.Text>
<Styled.Text>
{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.settingsTitle": "Change your audio settings",
"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.helpPermissionStep2": "Check browser and device settings to ensure microphone access is allowed.",
"app.audioModal.helpPermissionStep3": "Refresh the page and try again.",
"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.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.",