Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #3146 from matrix-org/bwindels/dontfailonmissingwe…
Browse files Browse the repository at this point in the history
…bcam

Don't show error dialog when user has no webcam
  • Loading branch information
bwindels authored Jun 27, 2019
2 parents f18c389 + 25aa65a commit dff6ca8
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 37 deletions.
5 changes: 5 additions & 0 deletions src/CallMediaHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ import * as Matrix from 'matrix-js-sdk';
import SettingsStore, {SettingLevel} from "./settings/SettingsStore";

export default {
hasAnyLabeledDevices: async function() {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.some(d => !!d.label);
},

getDevices: function() {
// Only needed for Electron atm, though should work in modern browsers
// once permission has been granted to the webapp
Expand Down
76 changes: 42 additions & 34 deletions src/components/views/settings/tabs/user/VoiceUserSettingsTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,48 +29,64 @@ export default class VoiceUserSettingsTab extends React.Component {
super();

this.state = {
mediaDevices: null,
mediaDevices: false,
activeAudioOutput: null,
activeAudioInput: null,
activeVideoInput: null,
};
}

componentWillMount(): void {
this._refreshMediaDevices();
async componentDidMount() {
const canSeeDeviceLabels = await CallMediaHandler.hasAnyLabeledDevices();
if (canSeeDeviceLabels) {
this._refreshMediaDevices();
}
}

_refreshMediaDevices = async (stream) => {
if (stream) {
// kill stream so that we don't leave it lingering around with webcam enabled etc
// as here we called gUM to ask user for permission to their device names only
stream.getTracks().forEach((track) => track.stop());
}

this.setState({
mediaDevices: await CallMediaHandler.getDevices(),
activeAudioOutput: CallMediaHandler.getAudioOutput(),
activeAudioInput: CallMediaHandler.getAudioInput(),
activeVideoInput: CallMediaHandler.getVideoInput(),
});
if (stream) {
// kill stream (after we've enumerated the devices, otherwise we'd get empty labels again)
// so that we don't leave it lingering around with webcam enabled etc
// as here we called gUM to ask user for permission to their device names only
stream.getTracks().forEach((track) => track.stop());
}
};

_requestMediaPermissions = () => {
const getUserMedia = (
window.navigator.getUserMedia || window.navigator.webkitGetUserMedia || window.navigator.mozGetUserMedia
);
if (getUserMedia) {
return getUserMedia.apply(window.navigator, [
{ video: true, audio: true },
this._refreshMediaDevices,
function() {
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
Modal.createTrackedDialog('No media permissions', '', ErrorDialog, {
title: _t('No media permissions'),
description: _t('You may need to manually permit Riot to access your microphone/webcam'),
});
},
]);
_requestMediaPermissions = async () => {
let constraints;
let stream;
let error;
try {
constraints = {video: true, audio: true};
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (err) {
// user likely doesn't have a webcam,
// we should still allow to select a microphone
if (err.name === "NotFoundError") {
constraints = { audio: true };
try {
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (err) {
error = err;
}
} else {
error = err;
}
}
if (error) {
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
Modal.createTrackedDialog('No media permissions', '', ErrorDialog, {
title: _t('No media permissions'),
description: _t('You may need to manually permit Riot to access your microphone/webcam'),
});
} else {
this._refreshMediaDevices(stream);
}
};

Expand Down Expand Up @@ -101,15 +117,7 @@ export default class VoiceUserSettingsTab extends React.Component {

_renderDeviceOptions(devices, category) {
return devices.map((d) => {
let label = d.label;
if (!label) {
switch (d.kind) {
case "audioinput": label = _t("Unnamed microphone"); break;
case "audiooutput": label = _t("Unnamed audio output"); break;
case "videoinput": label = _t("Unnamed camera"); break;
}
}
return (<option key={`${category}-${d.deviceId}`} value={d.deviceId}>{label}</option>);
return (<option key={`${category}-${d.deviceId}`} value={d.deviceId}>{d.label}</option>);
});
}

Expand Down
3 changes: 0 additions & 3 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -615,9 +615,6 @@
"Learn more about how we use analytics.": "Learn more about how we use analytics.",
"No media permissions": "No media permissions",
"You may need to manually permit Riot to access your microphone/webcam": "You may need to manually permit Riot to access your microphone/webcam",
"Unnamed microphone": "Unnamed microphone",
"Unnamed audio output": "Unnamed audio output",
"Unnamed camera": "Unnamed camera",
"Missing media permissions, click the button below to request.": "Missing media permissions, click the button below to request.",
"Request media permissions": "Request media permissions",
"No Audio Outputs detected": "No Audio Outputs detected",
Expand Down

0 comments on commit dff6ca8

Please sign in to comment.