Skip to content

Commit

Permalink
Stop dictate if microphone is not available (#2517)
Browse files Browse the repository at this point in the history
  • Loading branch information
compulim authored and corinagum committed Oct 30, 2019
1 parent 0b9187f commit 69b4a13
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixes [#2473](https://github.com/microsoft/BotFramework-WebChat/issues/2473). Fix samples 13 using wrong region for Speech Services credentials, by [@compulim](https://github.com/compulim) in PR [#2482](https://github.com/microsoft/BotFramework-WebChat/pull/2482)
- Fixes [#2420](https://github.com/microsoft/BotFramework-WebChat/issues/2420). Fix saga error should not result in an unhandled exception, by [@compulim](https://github.com/compulim) in PR [#2421](https://github.com/microsoft/BotFramework-WebChat/pull/2421)
- Fixes [#2513](https://github.com/microsoft/BotFramework-WebChat/issues/2513). Fix `core-js` not loading properly, by [@compulim](https://github.com/compulim) in PR [#2514](https://github.com/microsoft/BotFramework-WebChat/pull/2514)
- Fixes [#2516](https://github.com/microsoft/BotFramework-WebChat/issues/2516). Disable microphone input for `expecting` input hint on Safari, by [@compulim](https://github.com/compulim) in PR [#2517](https://github.com/microsoft/BotFramework-WebChat/pull/2517)

### Added

Expand Down
42 changes: 40 additions & 2 deletions packages/component/src/Dictation.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
import { Composer as DictateComposer } from 'react-dictate-button';
import { Constants } from 'botframework-webchat-core';
import PropTypes from 'prop-types';
import React, { useCallback } from 'react';
import React, { useCallback, useMemo } from 'react';

import connectToWebChat from './connectToWebChat';

const {
DictateState: { DICTATING, IDLE, STARTING }
} = Constants;

const PrefixedAudioContext = window.AudioContext || window.webkitAudioContext;

// The result of this check is asynchronous and it will fail on user interaction requirement.
async function canOpenMicrophone() {
const audioContext = new PrefixedAudioContext();

try {
if (audioContext.state === 'suspended') {
return await Promise.race([
audioContext.resume().then(() => true),
new Promise(resolve => setImmediate(resolve)).then(() => false)
]);
}

return true;
} finally {
await audioContext.close();
}
}

const Dictation = ({
dictateState,
disabled,
Expand Down Expand Up @@ -62,6 +82,24 @@ const Dictation = ({
onError && onError(event);
}, [dictateState, onError, setDictateState, stopDictate]);

const shouldStart = !disabled && (dictateState === STARTING || dictateState === DICTATING) && !numSpeakingActivities;

// We need to check if the browser allow us to do open microphone.
// In Safari, it block microphone access if the code was not executed based on user interaction.

// Since the check call is asynchronous, the result will always fail the user interaction requirement.
// Thus, we can never open microphone after we receive the check result.
// Instead, we will both open microphone and check the result. If the result is negative, we will close the microphone.

// TODO: [P3] Investigate if a resumed AudioContext instance is kept across multiple session, can we workaround Safari's restrictions.
useMemo(async () => {
if (shouldStart) {
const canStart = await canOpenMicrophone();

!canStart && stopDictate();
}
}, [shouldStart, stopDictate]);

return (
<DictateComposer
lang={language}
Expand All @@ -70,7 +108,7 @@ const Dictation = ({
onProgress={handleDictating}
speechGrammarList={SpeechGrammarList}
speechRecognition={SpeechRecognition}
started={!disabled && (dictateState === STARTING || dictateState === DICTATING) && !numSpeakingActivities}
started={shouldStart}
/>
);
};
Expand Down

0 comments on commit 69b4a13

Please sign in to comment.