diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index 77338404f..4539df1ff 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -16,17 +16,16 @@ limitations under the License. 'use strict'; -var React = require('react'); -var DragDropContext = require('react-dnd').DragDropContext; -var HTML5Backend = require('react-dnd-html5-backend'); -var sdk = require('matrix-react-sdk') -var dis = require('matrix-react-sdk/lib/dispatcher'); +import React from 'react'; +import { DragDropContext } from 'react-dnd'; +import HTML5Backend from 'react-dnd-html5-backend'; +import KeyCode from 'matrix-react-sdk/lib/KeyCode'; +import sdk from 'matrix-react-sdk'; +import dis from 'matrix-react-sdk/lib/dispatcher'; import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg'; - -var VectorConferenceHandler = require('../../VectorConferenceHandler'); -var CallHandler = require("matrix-react-sdk/lib/CallHandler"); - +import CallHandler from 'matrix-react-sdk/lib/CallHandler'; import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton'; +import VectorConferenceHandler from '../../VectorConferenceHandler'; var LeftPanel = React.createClass({ displayName: 'LeftPanel', @@ -42,6 +41,10 @@ var LeftPanel = React.createClass({ }; }, + componentWillMount: function() { + this.focusedElement = null; + }, + componentDidMount: function() { this.dispatcherRef = dis.register(this.onAction); }, @@ -64,6 +67,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 @@ -126,7 +214,8 @@ var LeftPanel = React.createClass({ } return ( -