From c6262d62a63fee8aad8546141e5898c400f73284 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 28 Apr 2017 18:21:22 +0100 Subject: [PATCH 01/18] webrtc config electron init on LoggedInView mounting configurable via UserSettings new class: CallMediaHandler Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/CallMediaHandler.js | 63 ++++++++++++++++++ src/components/structures/LoggedInView.js | 5 ++ src/components/structures/UserSettings.js | 78 ++++++++++++++++++++++- 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/CallMediaHandler.js diff --git a/src/CallMediaHandler.js b/src/CallMediaHandler.js new file mode 100644 index 0000000000..9133a6548d --- /dev/null +++ b/src/CallMediaHandler.js @@ -0,0 +1,63 @@ +/* + Copyright 2017 Michael Telatynski <7t3chguy@gmail.com> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import UserSettingsStore from './UserSettingsStore'; +import * as Matrix from 'matrix-js-sdk'; +import q from 'q'; + +export default { + getDevices: function() { + // Only needed for Electron atm, though should work in modern browsers + // once permission has been granted to the webapp + return navigator.mediaDevices.enumerateDevices().then(function(devices) { + const audioIn = {}; + const videoIn = {}; + + devices.forEach((device) => { + switch (device.kind) { + case 'audioinput': audioIn[device.deviceId] = device.label; break; + case 'videoinput': videoIn[device.deviceId] = device.label; break; + } + }); + + // console.log("Loaded WebRTC Devices", mediaDevices); + return { + audioinput: audioIn, + videoinput: videoIn, + }; + }, (error) => { console.log('Unable to refresh WebRTC Devices: ', error); }); + }, + + loadDevices: function() { + // this.getDevices().then((devices) => { + const localSettings = UserSettingsStore.getLocalSettings(); + // // if deviceId is not found, automatic fallback is in spec + // // recall previously stored inputs if any + Matrix.setMatrixCallAudioInput(localSettings['webrtc_audioinput']); + Matrix.setMatrixCallVideoInput(localSettings['webrtc_videoinput']); + // }); + }, + + setAudioInput: function(deviceId) { + UserSettingsStore.setLocalSetting('webrtc_audioinput', deviceId); + Matrix.setMatrixCallAudioInput(deviceId); + }, + + setVideoInput: function(deviceId) { + UserSettingsStore.setLocalSetting('webrtc_videoinput', deviceId); + Matrix.setMatrixCallVideoInput(deviceId); + }, +}; diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 9f01b0082b..8d18e92a0d 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -21,6 +21,7 @@ import React from 'react'; import KeyCode from '../../KeyCode'; import Notifier from '../../Notifier'; import PageTypes from '../../PageTypes'; +import CallMediaHandler from '../../CallMediaHandler'; import sdk from '../../index'; import dis from '../../dispatcher'; @@ -71,6 +72,10 @@ export default React.createClass({ // RoomView.getScrollState() this._scrollStateMap = {}; + // Only run these in electron, at least until a better mechanism for perms exists + // https://w3c.github.io/permissions/#dom-permissionname-device-info + if (window && window.process && window.process.type) CallMediaHandler.loadDevices(); + document.addEventListener('keydown', this._onKeyDown); }, diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index ba5d5780b4..05410e866f 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -24,6 +24,7 @@ var dis = require("../../dispatcher"); var q = require('q'); var package_json = require('../../../package.json'); var UserSettingsStore = require('../../UserSettingsStore'); +var CallMediaHandler = require('../../CallMediaHandler'); var GeminiScrollbar = require('react-gemini-scrollbar'); var Email = require('../../email'); var AddThreepid = require('../../AddThreepid'); @@ -109,7 +110,6 @@ const THEMES = [ } ]; - module.exports = React.createClass({ displayName: 'UserSettings', @@ -147,6 +147,7 @@ module.exports = React.createClass({ email_add_pending: false, vectorVersion: null, rejectingInvites: false, + mediaDevices: null, }; }, @@ -167,6 +168,18 @@ module.exports = React.createClass({ }); } + q().then(() => { + return CallMediaHandler.getDevices(); + }).then((mediaDevices) => { + console.log("got mediaDevices", mediaDevices, this._unmounted); + if (this._unmounted) return; + this.setState({ + mediaDevices, + activeAudioInput: this._localSettings['webrtc_audioinput'] || 'default', + activeVideoInput: this._localSettings['webrtc_videoinput'] || 'default', + }); + }); + // Bulk rejecting invites: // /sync won't have had time to return when UserSettings re-renders from state changes, so getRooms() // will still return rooms with invites. To get around this, add a listener for @@ -187,6 +200,8 @@ module.exports = React.createClass({ this._syncedSettings = syncedSettings; this._localSettings = UserSettingsStore.getLocalSettings(); + this._setAudioInput = this._setAudioInput.bind(this); + this._setVideoInput = this._setVideoInput.bind(this); }, componentDidMount: function() { @@ -775,6 +790,66 @@ module.exports = React.createClass({ ; }, + _mapWebRtcDevicesToSpans: function(devices) { + return Object.keys(devices).map( + (deviceId) => {devices[deviceId]} + ); + }, + + _setAudioInput: function(deviceId) { + this.setState({activeAudioInput: deviceId}); + CallMediaHandler.setAudioInput(deviceId); + }, + + _setVideoInput: function(deviceId) { + this.setState({activeVideoInput: deviceId}); + CallMediaHandler.setVideoInput(deviceId); + }, + + _renderWebRtcSettings: function() { + if (!(window && window.process && window.process.type) + || !this.state.mediaDevices) return; + + const Dropdown = sdk.getComponent('elements.Dropdown'); + + let microphoneDropdown =
No Microphones detected
; + let webcamDropdown =
No Webcams detected
; + + const audioInputs = this.state.mediaDevices.audioinput; + if ('default' in audioInputs) { + microphoneDropdown =
+

Microphone

+ + {this._mapWebRtcDevicesToSpans(audioInputs)} + +
; + } + + const videoInputs = this.state.mediaDevices.videoinput; + if ('default' in videoInputs) { + webcamDropdown =
+

Cameras

+ + {this._mapWebRtcDevicesToSpans(videoInputs)} + +
; + } + + return
+

WebRTC

+
+ {microphoneDropdown} + {webcamDropdown} +
+
; + }, + _showSpoiler: function(event) { const target = event.target; const hidden = target.getAttribute('data-spoiler'); @@ -973,6 +1048,7 @@ module.exports = React.createClass({ {this._renderUserInterfaceSettings()} {this._renderLabs()} + {this._renderWebRtcSettings()} {this._renderDevicesPanel()} {this._renderCryptoInfo()} {this._renderBulkOptions()} From b944fff5c5f97193c55dc1255545179be820fcef Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Fri, 5 May 2017 20:57:18 +0100 Subject: [PATCH 02/18] unscrew merge --- src/components/structures/UserSettings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 06103eae55..9d53bfda31 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -24,6 +24,7 @@ const dis = require("../../dispatcher"); const q = require('q'); const packageJson = require('../../../package.json'); const UserSettingsStore = require('../../UserSettingsStore'); +const CallMediaHandler = require('../../CallMediaHandler'); const GeminiScrollbar = require('react-gemini-scrollbar'); const Email = require('../../email'); const AddThreepid = require('../../AddThreepid'); From 09d0ab7df5f9e6602ca2e8e705e4d59a1304f94e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 May 2017 01:01:40 +0100 Subject: [PATCH 03/18] attempt to make media selector work everywhere (TM) loadDevices not only in electron Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/CallMediaHandler.js | 2 + src/components/structures/LoggedInView.js | 4 +- src/components/structures/UserSettings.js | 52 ++++++++++++++++------- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/CallMediaHandler.js b/src/CallMediaHandler.js index 9133a6548d..4f82e003b9 100644 --- a/src/CallMediaHandler.js +++ b/src/CallMediaHandler.js @@ -26,6 +26,8 @@ export default { const audioIn = {}; const videoIn = {}; + if (devices.some((device) => !device.label)) return false; + devices.forEach((device) => { switch (device.kind) { case 'audioinput': audioIn[device.deviceId] = device.label; break; diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index a84661bcd2..1a7b7e06e4 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -72,9 +72,7 @@ export default React.createClass({ // RoomView.getScrollState() this._scrollStateMap = {}; - // Only run these in electron, at least until a better mechanism for perms exists - // https://w3c.github.io/permissions/#dom-permissionname-device-info - if (window && window.process && window.process.type) CallMediaHandler.loadDevices(); + CallMediaHandler.loadDevices(); document.addEventListener('keydown', this._onKeyDown); }, diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index de88566300..58c6bb7c20 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -178,17 +178,7 @@ module.exports = React.createClass({ }); } - q().then(() => { - return CallMediaHandler.getDevices(); - }).then((mediaDevices) => { - console.log("got mediaDevices", mediaDevices, this._unmounted); - if (this._unmounted) return; - this.setState({ - mediaDevices, - activeAudioInput: this._localSettings['webrtc_audioinput'] || 'default', - activeVideoInput: this._localSettings['webrtc_videoinput'] || 'default', - }); - }); + this._refreshMediaDevices(); // Bulk rejecting invites: // /sync won't have had time to return when UserSettings re-renders from state changes, so getRooms() @@ -210,8 +200,6 @@ module.exports = React.createClass({ this._syncedSettings = syncedSettings; this._localSettings = UserSettingsStore.getLocalSettings(); - this._setAudioInput = this._setAudioInput.bind(this); - this._setVideoInput = this._setVideoInput.bind(this); }, componentDidMount: function() { @@ -233,6 +221,20 @@ module.exports = React.createClass({ } }, + _refreshMediaDevices: function() { + q().then(() => { + return CallMediaHandler.getDevices(); + }).then((mediaDevices) => { + // console.log("got mediaDevices", mediaDevices, this._unmounted); + if (this._unmounted) return; + this.setState({ + mediaDevices, + activeAudioInput: this._localSettings['webrtc_audioinput'] || 'default', + activeVideoInput: this._localSettings['webrtc_videoinput'] || 'default', + }); + }); + }, + _refreshFromServer: function() { const self = this; q.all([ @@ -818,9 +820,29 @@ module.exports = React.createClass({ CallMediaHandler.setVideoInput(deviceId); }, + _requestMediaPermissions: function() { + console.log("Request media perms"); + 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() {}, + ]); + } + }, + _renderWebRtcSettings: function() { - if (!(window && window.process && window.process.type) - || !this.state.mediaDevices) return; + if (this.state.mediaDevices === false) { + return
+

WebRTC

+
+
Missing Media Permissions, click to request.
+
+
; + } else if (!this.state.mediaDevices) return; const Dropdown = sdk.getComponent('elements.Dropdown'); From 8158ec6d54c062c6a3c49b92ee5c1fe1e64e969b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 May 2017 01:25:17 +0100 Subject: [PATCH 04/18] touchups Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 58c6bb7c20..0d182b27ab 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -820,8 +820,7 @@ module.exports = React.createClass({ CallMediaHandler.setVideoInput(deviceId); }, - _requestMediaPermissions: function() { - console.log("Request media perms"); + _requestMediaPermissions: function(event) { const getUserMedia = ( window.navigator.getUserMedia || window.navigator.webkitGetUserMedia || window.navigator.mozGetUserMedia ); @@ -829,7 +828,13 @@ module.exports = React.createClass({ return getUserMedia.apply(window.navigator, [ { video: true, audio: true }, this._refreshMediaDevices, - function() {}, + function() { + const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog'); + Modal.createDialog(ErrorDialog, { + title: "No media permissions", + description: "You may need to manually permit Riot to access your microphone/webcam", + }); + }, ]); } }, @@ -839,15 +844,17 @@ module.exports = React.createClass({ return

WebRTC

-
Missing Media Permissions, click to request.
+

+ Missing Media Permissions, click here to request. +

; } else if (!this.state.mediaDevices) return; const Dropdown = sdk.getComponent('elements.Dropdown'); - let microphoneDropdown =
No Microphones detected
; - let webcamDropdown =
No Webcams detected
; + let microphoneDropdown =

No Microphones detected

; + let webcamDropdown =

No Webcams detected

; const audioInputs = this.state.mediaDevices.audioinput; if ('default' in audioInputs) { From dbba1dedb6a529ce1198f2b2d85ec8e7b046c981 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Jun 2017 22:58:17 +0100 Subject: [PATCH 05/18] i18nize all the things and change show logic Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 22 ++++++++++------------ src/i18n/strings/en_EN.json | 6 ++++++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 4cb49d8c1e..b33bdd271d 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -902,9 +902,7 @@ module.exports = React.createClass({ }, _mapWebRtcDevicesToSpans: function(devices) { - return Object.keys(devices).map( - (deviceId) => {devices[deviceId]} - ); + return Object.keys(devices).map((deviceId) => {devices[deviceId]}); }, _setAudioInput: function(deviceId) { @@ -928,8 +926,8 @@ module.exports = React.createClass({ function() { const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog'); Modal.createDialog(ErrorDialog, { - title: "No media permissions", - description: "You may need to manually permit Riot to access your microphone/webcam", + title: _t('No media permissions'), + description: _t('You may need to manually permit Riot to access your microphone/webcam'), }); }, ]); @@ -939,10 +937,10 @@ module.exports = React.createClass({ _renderWebRtcSettings: function() { if (this.state.mediaDevices === false) { return
-

WebRTC

+

{_t('VoIP')}

- Missing Media Permissions, click here to request. + {_t('Missing Media Permissions, click here to request.')}

; @@ -950,11 +948,11 @@ module.exports = React.createClass({ const Dropdown = sdk.getComponent('elements.Dropdown'); - let microphoneDropdown =

No Microphones detected

; - let webcamDropdown =

No Webcams detected

; + let microphoneDropdown =

{_t('No Microphones detected')}

; + let webcamDropdown =

{_t('No Webcams detected')}

; const audioInputs = this.state.mediaDevices.audioinput; - if ('default' in audioInputs) { + if (Object.keys(videoInputs).length > 0) { microphoneDropdown =

Microphone

0) { webcamDropdown =

Cameras

-

WebRTC

+

{_t('VoIP')}

{microphoneDropdown} {webcamDropdown} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 211d164c2a..44a1af57fa 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -129,6 +129,12 @@ "Add email address": "Add email address", "Add phone number": "Add phone number", "Admin": "Admin", + "VoIP": "VoIP", + "Missing Media Permissions, click here to request.": "Missing Media Permissions, click here to request.", + "No Microphones detected": "No Microphones detected", + "No Webcams detected": "No Webcams detected", + "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", "Advanced": "Advanced", "Algorithm": "Algorithm", "Always show message timestamps": "Always show message timestamps", From 0c367783691629c551cea9ec02e1cd4fa6f5ccbe Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Jun 2017 22:59:37 +0100 Subject: [PATCH 06/18] fix bad indentation Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 44a1af57fa..dcf3670dd9 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -134,7 +134,7 @@ "No Microphones detected": "No Microphones detected", "No Webcams detected": "No Webcams detected", "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", + "You may need to manually permit Riot to access your microphone/webcam": "You may need to manually permit Riot to access your microphone/webcam", "Advanced": "Advanced", "Algorithm": "Algorithm", "Always show message timestamps": "Always show message timestamps", From aa90d6b097d4b541b1d260f4655482d4c2d117fb Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Jun 2017 23:00:25 +0100 Subject: [PATCH 07/18] fix **AMAZING** C&P derp Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index b33bdd271d..f660cf71e1 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -952,7 +952,7 @@ module.exports = React.createClass({ let webcamDropdown =

{_t('No Webcams detected')}

; const audioInputs = this.state.mediaDevices.audioinput; - if (Object.keys(videoInputs).length > 0) { + if (Object.keys(audioInputs).length > 0) { microphoneDropdown =

Microphone

Date: Thu, 1 Jun 2017 23:25:44 +0100 Subject: [PATCH 08/18] change device data structure to array of objects so that we can set falsey values, for unsetting device most dolphinately needs testing Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/CallMediaHandler.js | 8 ++++---- src/components/structures/UserSettings.js | 17 ++++++++++++----- src/i18n/strings/en_EN.json | 1 + 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/CallMediaHandler.js b/src/CallMediaHandler.js index 4f82e003b9..45ca5dc30d 100644 --- a/src/CallMediaHandler.js +++ b/src/CallMediaHandler.js @@ -23,15 +23,15 @@ export default { // Only needed for Electron atm, though should work in modern browsers // once permission has been granted to the webapp return navigator.mediaDevices.enumerateDevices().then(function(devices) { - const audioIn = {}; - const videoIn = {}; + const audioIn = []; + const videoIn = []; if (devices.some((device) => !device.label)) return false; devices.forEach((device) => { switch (device.kind) { - case 'audioinput': audioIn[device.deviceId] = device.label; break; - case 'videoinput': videoIn[device.deviceId] = device.label; break; + case 'audioinput': audioIn.push(device); break; + case 'videoinput': videoIn.push(device); break; } }); diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index f660cf71e1..fcb7a70559 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -269,8 +269,8 @@ module.exports = React.createClass({ if (this._unmounted) return; this.setState({ mediaDevices, - activeAudioInput: this._localSettings['webrtc_audioinput'] || 'default', - activeVideoInput: this._localSettings['webrtc_videoinput'] || 'default', + activeAudioInput: this._localSettings['webrtc_audioinput'], + activeVideoInput: this._localSettings['webrtc_videoinput'], }); }); }, @@ -902,7 +902,7 @@ module.exports = React.createClass({ }, _mapWebRtcDevicesToSpans: function(devices) { - return Object.keys(devices).map((deviceId) => {devices[deviceId]}); + return devices.map((device) => {devices[device.deviceId]}); }, _setAudioInput: function(deviceId) { @@ -951,8 +951,14 @@ module.exports = React.createClass({ let microphoneDropdown =

{_t('No Microphones detected')}

; let webcamDropdown =

{_t('No Webcams detected')}

; + const defaultOption = { + deviceId: undefined, + label: _t('Default Device'), + }; + const audioInputs = this.state.mediaDevices.audioinput; - if (Object.keys(audioInputs).length > 0) { + if (audioInputs.length > 0) { + audioInputs.unshift(defaultOption); microphoneDropdown =

Microphone

0) { + if (videoInputs.length > 0) { + videoInputs.unshift(defaultOption); webcamDropdown =

Cameras

Date: Thu, 1 Jun 2017 23:33:36 +0100 Subject: [PATCH 09/18] only unshift default if there is no deviceId===default Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index fcb7a70559..5dd6a7fec2 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -958,7 +958,9 @@ module.exports = React.createClass({ const audioInputs = this.state.mediaDevices.audioinput; if (audioInputs.length > 0) { - audioInputs.unshift(defaultOption); + if (!audioInputs.some((input) => input.deviceId === 'default')) { + audioInputs.unshift(defaultOption); + } microphoneDropdown =

Microphone

0) { - videoInputs.unshift(defaultOption); + if (!videoInputs.some((input) => input.deviceId === 'default')) { + videoInputs.unshift(defaultOption); + } webcamDropdown =

Cameras

Date: Thu, 1 Jun 2017 23:39:54 +0100 Subject: [PATCH 10/18] lets actually make things work, eh? Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 5dd6a7fec2..9a55094edf 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -902,7 +902,7 @@ module.exports = React.createClass({ }, _mapWebRtcDevicesToSpans: function(devices) { - return devices.map((device) => {devices[device.deviceId]}); + return devices.map((device) => {device.label}); }, _setAudioInput: function(deviceId) { From beedeec1636e0d43938b0edeaf688a98b78117ff Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Jun 2017 23:50:14 +0100 Subject: [PATCH 11/18] copy the arrays so we're not making a mess Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 9a55094edf..b5d5c23296 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -956,7 +956,7 @@ module.exports = React.createClass({ label: _t('Default Device'), }; - const audioInputs = this.state.mediaDevices.audioinput; + const audioInputs = this.state.mediaDevices.audioinput.slice(0); if (audioInputs.length > 0) { if (!audioInputs.some((input) => input.deviceId === 'default')) { audioInputs.unshift(defaultOption); @@ -972,7 +972,7 @@ module.exports = React.createClass({
; } - const videoInputs = this.state.mediaDevices.videoinput; + const videoInputs = this.state.mediaDevices.videoinput.slice(0); if (videoInputs.length > 0) { if (!videoInputs.some((input) => input.deviceId === 'default')) { videoInputs.unshift(defaultOption); From 3eb519b2275de34461edb67c99ab1af493b96c33 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Jun 2017 23:54:17 +0100 Subject: [PATCH 12/18] this is just endless Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index b5d5c23296..b8567fc180 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -958,14 +958,18 @@ module.exports = React.createClass({ const audioInputs = this.state.mediaDevices.audioinput.slice(0); if (audioInputs.length > 0) { + let defaultInput; if (!audioInputs.some((input) => input.deviceId === 'default')) { audioInputs.unshift(defaultOption); + } else { + defaultInput = 'default'; } + microphoneDropdown =

Microphone

{this._mapWebRtcDevicesToSpans(audioInputs)} @@ -974,14 +978,18 @@ module.exports = React.createClass({ const videoInputs = this.state.mediaDevices.videoinput.slice(0); if (videoInputs.length > 0) { + let defaultInput; if (!videoInputs.some((input) => input.deviceId === 'default')) { videoInputs.unshift(defaultOption); + } else { + defaultInput = 'default'; } + webcamDropdown =

Cameras

{this._mapWebRtcDevicesToSpans(videoInputs)} From 46a93266073ba60644d335665417a3e2aa36392f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 2 Jun 2017 00:20:34 +0100 Subject: [PATCH 13/18] special case default - CallMediaHandler can figure it out Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/CallMediaHandler.js | 24 +++++++++++++++++++++++ src/components/structures/UserSettings.js | 16 +++++---------- src/i18n/strings/en_EN.json | 2 ++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/CallMediaHandler.js b/src/CallMediaHandler.js index 45ca5dc30d..780df60846 100644 --- a/src/CallMediaHandler.js +++ b/src/CallMediaHandler.js @@ -53,12 +53,36 @@ export default { // }); }, + _findDefault: function(devices) { + return devices.some((device) => device.deviceId === 'default') ? 'default' : undefined; + }, + + setAudioInputDefault: async function() { + const devices = await this.getDevices(); + const audioDefault = this._findDefault(devices.audioinput); + this._setAudioInput(audioDefault); + }, + setAudioInput: function(deviceId) { + this[deviceId === 'default' ? 'setAudioInputDefault' : '_setAudioInput'](deviceId); + }, + + _setAudioInput: function(deviceId) { UserSettingsStore.setLocalSetting('webrtc_audioinput', deviceId); Matrix.setMatrixCallAudioInput(deviceId); }, + setVideoInputDefault: async function() { + const devices = await this.getDevices(); + const videoDefault = this._findDefault(devices.videoinput); + this._setVideoInput(videoDefault); + }, + setVideoInput: function(deviceId) { + this[deviceId === 'default' ? 'setVideoInputDefault' : '_setVideoInput'](); + }, + + _setVideoInput: function(deviceId) { UserSettingsStore.setLocalSetting('webrtc_videoinput', deviceId); Matrix.setMatrixCallVideoInput(deviceId); }, diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index b8567fc180..99b02b59f9 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -952,24 +952,21 @@ module.exports = React.createClass({ let webcamDropdown =

{_t('No Webcams detected')}

; const defaultOption = { - deviceId: undefined, + deviceId: 'default', label: _t('Default Device'), }; const audioInputs = this.state.mediaDevices.audioinput.slice(0); if (audioInputs.length > 0) { - let defaultInput; if (!audioInputs.some((input) => input.deviceId === 'default')) { audioInputs.unshift(defaultOption); - } else { - defaultInput = 'default'; } microphoneDropdown =
-

Microphone

+

{_t('Microphone')}

{this._mapWebRtcDevicesToSpans(audioInputs)} @@ -978,18 +975,15 @@ module.exports = React.createClass({ const videoInputs = this.state.mediaDevices.videoinput.slice(0); if (videoInputs.length > 0) { - let defaultInput; if (!videoInputs.some((input) => input.deviceId === 'default')) { videoInputs.unshift(defaultOption); - } else { - defaultInput = 'default'; } webcamDropdown =
-

Cameras

+

{_t('Camera')}

{this._mapWebRtcDevicesToSpans(videoInputs)} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 3a8752fd5d..b9ac79d362 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -136,6 +136,8 @@ "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", "Default Device": "Default Device", + "Microphone": "Microphone", + "Cameras": "Cameras", "Advanced": "Advanced", "Algorithm": "Algorithm", "Always show message timestamps": "Always show message timestamps", From 4976cbb4240acc32bc2cc88c36c48d2d06a847ec Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 2 Jun 2017 00:21:34 +0100 Subject: [PATCH 14/18] missed a thing Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/CallMediaHandler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CallMediaHandler.js b/src/CallMediaHandler.js index 780df60846..d5813c1d5c 100644 --- a/src/CallMediaHandler.js +++ b/src/CallMediaHandler.js @@ -79,7 +79,7 @@ export default { }, setVideoInput: function(deviceId) { - this[deviceId === 'default' ? 'setVideoInputDefault' : '_setVideoInput'](); + this[deviceId === 'default' ? 'setVideoInputDefault' : '_setVideoInput'](deviceId); }, _setVideoInput: function(deviceId) { From 0bafd6458a0a6a06b8d9f14dff097cffc75e297e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 2 Jun 2017 00:26:31 +0100 Subject: [PATCH 15/18] Revert voodoo --- src/CallMediaHandler.js | 24 ----------------------- src/components/structures/UserSettings.js | 16 ++++++++++----- src/i18n/strings/en_EN.json | 2 -- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/CallMediaHandler.js b/src/CallMediaHandler.js index d5813c1d5c..45ca5dc30d 100644 --- a/src/CallMediaHandler.js +++ b/src/CallMediaHandler.js @@ -53,36 +53,12 @@ export default { // }); }, - _findDefault: function(devices) { - return devices.some((device) => device.deviceId === 'default') ? 'default' : undefined; - }, - - setAudioInputDefault: async function() { - const devices = await this.getDevices(); - const audioDefault = this._findDefault(devices.audioinput); - this._setAudioInput(audioDefault); - }, - setAudioInput: function(deviceId) { - this[deviceId === 'default' ? 'setAudioInputDefault' : '_setAudioInput'](deviceId); - }, - - _setAudioInput: function(deviceId) { UserSettingsStore.setLocalSetting('webrtc_audioinput', deviceId); Matrix.setMatrixCallAudioInput(deviceId); }, - setVideoInputDefault: async function() { - const devices = await this.getDevices(); - const videoDefault = this._findDefault(devices.videoinput); - this._setVideoInput(videoDefault); - }, - setVideoInput: function(deviceId) { - this[deviceId === 'default' ? 'setVideoInputDefault' : '_setVideoInput'](deviceId); - }, - - _setVideoInput: function(deviceId) { UserSettingsStore.setLocalSetting('webrtc_videoinput', deviceId); Matrix.setMatrixCallVideoInput(deviceId); }, diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 99b02b59f9..b8567fc180 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -952,21 +952,24 @@ module.exports = React.createClass({ let webcamDropdown =

{_t('No Webcams detected')}

; const defaultOption = { - deviceId: 'default', + deviceId: undefined, label: _t('Default Device'), }; const audioInputs = this.state.mediaDevices.audioinput.slice(0); if (audioInputs.length > 0) { + let defaultInput; if (!audioInputs.some((input) => input.deviceId === 'default')) { audioInputs.unshift(defaultOption); + } else { + defaultInput = 'default'; } microphoneDropdown =
-

{_t('Microphone')}

+

Microphone

{this._mapWebRtcDevicesToSpans(audioInputs)} @@ -975,15 +978,18 @@ module.exports = React.createClass({ const videoInputs = this.state.mediaDevices.videoinput.slice(0); if (videoInputs.length > 0) { + let defaultInput; if (!videoInputs.some((input) => input.deviceId === 'default')) { videoInputs.unshift(defaultOption); + } else { + defaultInput = 'default'; } webcamDropdown =
-

{_t('Camera')}

+

Cameras

{this._mapWebRtcDevicesToSpans(videoInputs)} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b9ac79d362..3a8752fd5d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -136,8 +136,6 @@ "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", "Default Device": "Default Device", - "Microphone": "Microphone", - "Cameras": "Cameras", "Advanced": "Advanced", "Algorithm": "Algorithm", "Always show message timestamps": "Always show message timestamps", From 6b4daf02a9d6522d695b9b8be440f46be7685df8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 2 Jun 2017 00:27:20 +0100 Subject: [PATCH 16/18] i18 missed things Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 4 ++-- src/i18n/strings/en_EN.json | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index b8567fc180..837cf99f1a 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -966,7 +966,7 @@ module.exports = React.createClass({ } microphoneDropdown =
-

Microphone

+

{_t('Microphone')}

-

Cameras

+

{_t('Camera')}

Date: Fri, 2 Jun 2017 00:31:43 +0100 Subject: [PATCH 17/18] try empty string as falsey key Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 837cf99f1a..389f08fd3b 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -952,7 +952,7 @@ module.exports = React.createClass({ let webcamDropdown =

{_t('No Webcams detected')}

; const defaultOption = { - deviceId: undefined, + deviceId: '', label: _t('Default Device'), }; From b1973d799860535577ee1234277540f2ed3a71b5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 2 Jun 2017 00:42:19 +0100 Subject: [PATCH 18/18] undefined =/= '' Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 389f08fd3b..7300d82541 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -958,7 +958,7 @@ module.exports = React.createClass({ const audioInputs = this.state.mediaDevices.audioinput.slice(0); if (audioInputs.length > 0) { - let defaultInput; + let defaultInput = ''; if (!audioInputs.some((input) => input.deviceId === 'default')) { audioInputs.unshift(defaultOption); } else { @@ -978,7 +978,7 @@ module.exports = React.createClass({ const videoInputs = this.state.mediaDevices.videoinput.slice(0); if (videoInputs.length > 0) { - let defaultInput; + let defaultInput = ''; if (!videoInputs.some((input) => input.deviceId === 'default')) { videoInputs.unshift(defaultOption); } else {