diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index a9df37a8b8..2d97313a07 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -19,9 +19,11 @@ limitations under the License. var React = require('react'); var DragDropContext = require('react-dnd').DragDropContext; var HTML5Backend = require('react-dnd-html5-backend'); +var KeyCode = require('matrix-react-sdk/lib/KeyCode'); var sdk = require('matrix-react-sdk') var dis = require('matrix-react-sdk/lib/dispatcher'); + var VectorConferenceHandler = require('../../VectorConferenceHandler'); var CallHandler = require("matrix-react-sdk/lib/CallHandler"); @@ -40,6 +42,10 @@ var LeftPanel = React.createClass({ }; }, + componentWillMount: function() { + this.focusedElement = null; + }, + componentDidMount: function() { this.dispatcherRef = dis.register(this.onAction); }, @@ -62,6 +68,91 @@ var LeftPanel = React.createClass({ } }, + _onFocus: function(ev) { + this.focusedElement = ev.target; + }, + + _onBlur: function(ev) { + this.focusedElement = null; + }, + + _onKeyDown: function(ev) { + if (!this.focusedElement) return; + let handled = false; + + switch (ev.keyCode) { + case KeyCode.UP: + this._onMoveFocus(true); + handled = true; + break; + case KeyCode.DOWN: + this._onMoveFocus(false); + handled = true; + break; + } + + if (handled) { + ev.stopPropagation(); + ev.preventDefault(); + } + }, + + _onMoveFocus: function(up) { + var element = this.focusedElement; + + // unclear why this isn't needed + // var descending = (up == this.focusDirection) ? this.focusDescending : !this.focusDescending; + // this.focusDirection = up; + + var descending = false; // are we currently descending or ascending through the DOM tree? + var classes; + + do { + var child = up ? element.lastElementChild : element.firstElementChild; + var sibling = up ? element.previousElementSibling : element.nextElementSibling; + + if (descending) { + if (child) { + element = child; + } + else if (sibling) { + element = sibling; + } + else { + descending = false; + element = element.parentElement; + } + } + else { + if (sibling) { + element = sibling; + descending = true; + } + else { + element = element.parentElement; + } + } + + if (element) { + classes = element.classList; + if (classes.contains("mx_LeftPanel")) { // we hit the top + element = up ? element.lastElementChild : element.firstElementChild; + descending = true; + } + } + + } while(element && !( + classes.contains("mx_RoomTile") || + classes.contains("mx_SearchBox_search") || + classes.contains("mx_RoomSubList_ellipsis"))); + + if (element) { + element.focus(); + this.focusedElement = element; + this.focusedDescending = descending; + } + }, + _recheckCallElement: function(selectedRoomId) { // if we aren't viewing a room with an ongoing call, but there is an // active call, show the call element - we need to do this to make @@ -120,7 +211,8 @@ var LeftPanel = React.createClass({ } return ( -