Keyboard shortcuts to mute microphone/camera

Same as hangouts: ctrl-d for mute microphone; ctrl-e to mute camera.
This commit is contained in:
Richard van der Hoff 2016-10-17 14:03:37 +01:00
parent 658224a1bd
commit 4f901f1894
2 changed files with 87 additions and 58 deletions

View file

@ -29,4 +29,6 @@ module.exports = {
RIGHT: 39, RIGHT: 39,
DOWN: 40, DOWN: 40,
DELETE: 46, DELETE: 46,
KEY_D: 68,
KEY_E: 69,
}; };

View file

@ -38,6 +38,8 @@ var rate_limited_func = require('../../ratelimitedfunc');
var ObjectUtils = require('../../ObjectUtils'); var ObjectUtils = require('../../ObjectUtils');
var Rooms = require('../../Rooms'); var Rooms = require('../../Rooms');
import KeyCode from '../../KeyCode';
import UserProvider from '../../autocomplete/UserProvider'; import UserProvider from '../../autocomplete/UserProvider';
var DEBUG = false; var DEBUG = false;
@ -239,11 +241,65 @@ module.exports = React.createClass({
} }
}, },
componentDidMount: function() {
var call = this._getCallForRoom();
var callState = call ? call.call_state : "ended";
this.setState({
callState: callState
});
this._updateConfCallNotification();
window.addEventListener('resize', this.onResize);
this.onResize();
document.addEventListener("keydown", this.onKeyDown);
// XXX: EVIL HACK to autofocus inviting on empty rooms.
// We use the setTimeout to avoid racing with focus_composer.
if (this.state.room &&
this.state.room.getJoinedMembers().length == 1 &&
this.state.room.getLiveTimeline() &&
this.state.room.getLiveTimeline().getEvents() &&
this.state.room.getLiveTimeline().getEvents().length <= 6)
{
var inviteBox = document.getElementById("mx_SearchableEntityList_query");
setTimeout(function() {
if (inviteBox) {
inviteBox.focus();
}
}, 50);
}
},
componentWillReceiveProps: function(newProps) {
if (newProps.roomAddress != this.props.roomAddress) {
throw new Error("changing room on a RoomView is not supported");
}
if (newProps.eventId != this.props.eventId) {
// when we change focussed event id, hide the search results.
this.setState({searchResults: null});
}
},
shouldComponentUpdate: function(nextProps, nextState) { shouldComponentUpdate: function(nextProps, nextState) {
return (!ObjectUtils.shallowEqual(this.props, nextProps) || return (!ObjectUtils.shallowEqual(this.props, nextProps) ||
!ObjectUtils.shallowEqual(this.state, nextState)); !ObjectUtils.shallowEqual(this.state, nextState));
}, },
componentDidUpdate: function() {
if (this.refs.roomView) {
var roomView = ReactDOM.findDOMNode(this.refs.roomView);
if (!roomView.ondrop) {
roomView.addEventListener('drop', this.onDrop);
roomView.addEventListener('dragover', this.onDragOver);
roomView.addEventListener('dragleave', this.onDragLeaveOrEnd);
roomView.addEventListener('dragend', this.onDragLeaveOrEnd);
}
}
},
componentWillUnmount: function() { componentWillUnmount: function() {
// set a boolean to say we've been unmounted, which any pending // set a boolean to say we've been unmounted, which any pending
// promises can use to throw away their results. // promises can use to throw away their results.
@ -273,6 +329,8 @@ module.exports = React.createClass({
window.removeEventListener('resize', this.onResize); window.removeEventListener('resize', this.onResize);
document.removeEventListener("keydown", this.onKeyDown);
// cancel any pending calls to the rate_limited_funcs // cancel any pending calls to the rate_limited_funcs
this._updateRoomMembers.cancelPendingCall(); this._updateRoomMembers.cancelPendingCall();
@ -281,6 +339,31 @@ module.exports = React.createClass({
// Tinter.tint(); // reset colourscheme // Tinter.tint(); // reset colourscheme
}, },
onKeyDown: function(ev) {
var handled = false;
switch (ev.keyCode) {
case KeyCode.KEY_D:
if (ev.ctrlKey) {
this.onMuteAudioClick();
handled = true;
}
break;
case KeyCode.KEY_E:
if (ev.ctrlKey) {
this.onMuteVideoClick();
handled = true;
}
break;
}
if (handled) {
ev.stopPropagation();
ev.preventDefault();
}
},
onAction: function(payload) { onAction: function(payload) {
switch (payload.action) { switch (payload.action) {
case 'message_send_failed': case 'message_send_failed':
@ -326,17 +409,6 @@ module.exports = React.createClass({
} }
}, },
componentWillReceiveProps: function(newProps) {
if (newProps.roomAddress != this.props.roomAddress) {
throw new Error("changing room on a RoomView is not supported");
}
if (newProps.eventId != this.props.eventId) {
// when we change focussed event id, hide the search results.
this.setState({searchResults: null});
}
},
onRoomTimeline: function(ev, room, toStartOfTimeline, removed, data) { onRoomTimeline: function(ev, room, toStartOfTimeline, removed, data) {
if (this.unmounted) return; if (this.unmounted) return;
@ -573,47 +645,6 @@ module.exports = React.createClass({
}); });
}, },
componentDidMount: function() {
var call = this._getCallForRoom();
var callState = call ? call.call_state : "ended";
this.setState({
callState: callState
});
this._updateConfCallNotification();
window.addEventListener('resize', this.onResize);
this.onResize();
// XXX: EVIL HACK to autofocus inviting on empty rooms.
// We use the setTimeout to avoid racing with focus_composer.
if (this.state.room &&
this.state.room.getJoinedMembers().length == 1 &&
this.state.room.getLiveTimeline() &&
this.state.room.getLiveTimeline().getEvents() &&
this.state.room.getLiveTimeline().getEvents().length <= 6)
{
var inviteBox = document.getElementById("mx_SearchableEntityList_query");
setTimeout(function() {
if (inviteBox) {
inviteBox.focus();
}
}, 50);
}
},
componentDidUpdate: function() {
if (this.refs.roomView) {
var roomView = ReactDOM.findDOMNode(this.refs.roomView);
if (!roomView.ondrop) {
roomView.addEventListener('drop', this.onDrop);
roomView.addEventListener('dragover', this.onDragOver);
roomView.addEventListener('dragleave', this.onDragLeaveOrEnd);
roomView.addEventListener('dragend', this.onDragLeaveOrEnd);
}
}
},
onSearchResultsResize: function() { onSearchResultsResize: function() {
dis.dispatch({ action: 'timeline_resize' }, true); dis.dispatch({ action: 'timeline_resize' }, true);
}, },
@ -1261,9 +1292,7 @@ module.exports = React.createClass({
} }
var newState = !call.isMicrophoneMuted(); var newState = !call.isMicrophoneMuted();
call.setMicrophoneMuted(newState); call.setMicrophoneMuted(newState);
this.setState({ this.forceUpdate(); // TODO: just update the voip buttons
audioMuted: newState
});
}, },
onMuteVideoClick: function() { onMuteVideoClick: function() {
@ -1273,9 +1302,7 @@ module.exports = React.createClass({
} }
var newState = !call.isLocalVideoMuted(); var newState = !call.isLocalVideoMuted();
call.setLocalVideoMuted(newState); call.setLocalVideoMuted(newState);
this.setState({ this.forceUpdate(); // TODO: just update the voip buttons
videoMuted: newState
});
}, },
onChildResize: function() { onChildResize: function() {