diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 59346d5f4d..0da741df19 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -63,12 +63,15 @@ module.exports = React.createClass({ var s = this.getRoomLists(); this.setState(s); + + this.focusedRoomTileRoomId = null; }, componentDidMount: function() { this.dispatcherRef = dis.register(this.onAction); // Initialise the stickyHeaders when the component is created this._updateStickyHeaders(true); + document.addEventListener('keydown', this._onKeyDown); }, componentDidUpdate: function() { @@ -100,6 +103,8 @@ module.exports = React.createClass({ // Force an update because the notif count state is too deep to cause // an update. This forces the local echo of reading notifs to be // reflected by the RoomTiles. + // + // FIXME: we should surely just be refreshing the right tile... this.forceUpdate(); break; } @@ -120,6 +125,8 @@ module.exports = React.createClass({ } // cancel any pending calls to the rate_limited_funcs this._delayedRefreshRoomList.cancelPendingCall(); + document.removeEventListener('keydown', this._onKeyDown); + }, onRoom: function(room) { @@ -149,6 +156,35 @@ module.exports = React.createClass({ } }, + _onMouseOver: function(ev) { + this._lastMouseOverTs = Date.now(); + }, + + _onKeyDown: function(ev) { + if (!this.focusedRoomTileRoomId) 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) { + + }, + onSubListHeaderClick: function(isHidden, scrollToPosition) { // The scroll area has expanded or contracted, so re-calculate sticky headers positions this._updateStickyHeaders(true, scrollToPosition); @@ -192,7 +228,15 @@ module.exports = React.createClass({ }, _delayedRefreshRoomList: new rate_limited_func(function() { - this.refreshRoomList(); + // if the mouse has been moving over the RoomList in the last 500ms + // then delay the refresh further to avoid bouncing around under the + // cursor + if (Date.now() - this._lastMouseOverTs > 500) { + this.refreshRoomList(); + } + else { + this._delayedRefreshRoomList(); + } }, 500), refreshRoomList: function() { @@ -207,7 +251,8 @@ module.exports = React.createClass({ // us re-rendering all the sublists every time anything changes anywhere // in the state of the client. this.setState(this.getRoomLists()); - this._lastRefreshRoomListTs = Date.now(); + + // this._lastRefreshRoomListTs = Date.now(); }, getRoomLists: function() { @@ -457,6 +502,10 @@ module.exports = React.createClass({ this.refs.gemscroll.forceUpdate(); }, + onRoomTileFocus: function(roomId) { + this.focusedRoomTileRoomId = roomId; + }, + render: function() { var RoomSubList = sdk.getComponent('structures.RoomSubList'); var self = this; @@ -464,7 +513,7 @@ module.exports = React.createClass({ return ( -
+
{ Object.keys(self.state.lists).map(function(tagName) { @@ -529,6 +582,7 @@ module.exports = React.createClass({ collapsed={ self.props.collapsed } searchFilter={ self.props.searchFilter } onHeaderClick={ self.onSubListHeaderClick } + onRoomTileFocus={ self.onRoomTileFocus } onShowMoreRooms={ self.onShowMoreRooms } />; } @@ -545,6 +599,7 @@ module.exports = React.createClass({ collapsed={ self.props.collapsed } searchFilter={ self.props.searchFilter } onHeaderClick={ self.onSubListHeaderClick } + onRoomTileFocus={ self.onRoomTileFocus } onShowMoreRooms={ self.onShowMoreRooms } />
diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 06b05e9299..cff5c2f623 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -35,6 +35,7 @@ module.exports = React.createClass({ connectDragSource: React.PropTypes.func, connectDropTarget: React.PropTypes.func, onClick: React.PropTypes.func, + onFocus: React.PropTypes.func, isDragging: React.PropTypes.bool, room: React.PropTypes.object.isRequired, @@ -104,6 +105,12 @@ module.exports = React.createClass({ } }, + onFocus: function() { + if (this.props.onFocus) { + this.props.onFocus(this.props.room.roomId); + } + }, + onMouseEnter: function() { this.setState( { hover : true }); this.badgeOnMouseEnter(); @@ -255,7 +262,9 @@ module.exports = React.createClass({ let ret = (
{ /* Only native elements can be wrapped in a DnD object. */} - +