mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-18 06:35:35 +08:00
Merge pull request #262 from matrix-org/rav/pageup_down
Catch pageup/down and ctrl-home/end at the top level
This commit is contained in:
commit
b70f518d66
32
src/KeyCode.js
Normal file
32
src/KeyCode.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* a selection of key codes, as used in KeyboardEvent.keyCode */
|
||||||
|
module.exports = {
|
||||||
|
BACKSPACE: 8,
|
||||||
|
TAB: 9,
|
||||||
|
ENTER: 13,
|
||||||
|
SHIFT: 16,
|
||||||
|
PAGE_UP: 33,
|
||||||
|
PAGE_DOWN: 34,
|
||||||
|
END: 35,
|
||||||
|
HOME: 36,
|
||||||
|
LEFT: 37,
|
||||||
|
UP: 38,
|
||||||
|
RIGHT: 39,
|
||||||
|
DOWN: 40,
|
||||||
|
DELETE: 46,
|
||||||
|
};
|
@ -35,6 +35,7 @@ var Tinter = require("../../Tinter");
|
|||||||
var sdk = require('../../index');
|
var sdk = require('../../index');
|
||||||
var MatrixTools = require('../../MatrixTools');
|
var MatrixTools = require('../../MatrixTools');
|
||||||
var linkifyMatrix = require("../../linkify-matrix");
|
var linkifyMatrix = require("../../linkify-matrix");
|
||||||
|
var KeyCode = require('../../KeyCode');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'MatrixChat',
|
displayName: 'MatrixChat',
|
||||||
@ -722,11 +723,10 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onKeyDown: function(ev) {
|
onKeyDown: function(ev) {
|
||||||
if (ev.altKey) {
|
|
||||||
/*
|
/*
|
||||||
// Remove this for now as ctrl+alt = alt-gr so this breaks keyboards which rely on alt-gr for numbers
|
// Remove this for now as ctrl+alt = alt-gr so this breaks keyboards which rely on alt-gr for numbers
|
||||||
// Will need to find a better meta key if anyone actually cares about using this.
|
// Will need to find a better meta key if anyone actually cares about using this.
|
||||||
if (ev.ctrlKey && ev.keyCode > 48 && ev.keyCode < 58) {
|
if (ev.altKey && ev.ctrlKey && ev.keyCode > 48 && ev.keyCode < 58) {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'view_indexed_room',
|
action: 'view_indexed_room',
|
||||||
roomIndex: ev.keyCode - 49,
|
roomIndex: ev.keyCode - 49,
|
||||||
@ -736,18 +736,45 @@ module.exports = React.createClass({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
switch (ev.keyCode) {
|
|
||||||
case 38:
|
var handled = false;
|
||||||
dis.dispatch({action: 'view_prev_room'});
|
|
||||||
ev.stopPropagation();
|
switch (ev.keyCode) {
|
||||||
ev.preventDefault();
|
case KeyCode.UP:
|
||||||
break;
|
case KeyCode.DOWN:
|
||||||
case 40:
|
if (ev.altKey) {
|
||||||
dis.dispatch({action: 'view_next_room'});
|
var action = ev.keyCode == KeyCode.UP ?
|
||||||
ev.stopPropagation();
|
'view_prev_room' : 'view_next_room';
|
||||||
ev.preventDefault();
|
dis.dispatch({action: action});
|
||||||
break;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KeyCode.PAGE_UP:
|
||||||
|
case KeyCode.PAGE_DOWN:
|
||||||
|
this._onScrollKeyPressed(ev);
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KeyCode.HOME:
|
||||||
|
case KeyCode.END:
|
||||||
|
if (ev.ctrlKey) {
|
||||||
|
this._onScrollKeyPressed(ev);
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
ev.preventDefault();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** dispatch a page-up/page-down/etc to the appropriate component */
|
||||||
|
_onScrollKeyPressed(ev) {
|
||||||
|
if (this.refs.roomView) {
|
||||||
|
this.refs.roomView.handleScrollKey(ev);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -132,6 +132,14 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* jump to the top of the content.
|
||||||
|
*/
|
||||||
|
scrollToTop: function() {
|
||||||
|
if (this.refs.scrollPanel) {
|
||||||
|
this.refs.scrollPanel.scrollToTop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/* jump to the bottom of the content.
|
/* jump to the bottom of the content.
|
||||||
*/
|
*/
|
||||||
scrollToBottom: function() {
|
scrollToBottom: function() {
|
||||||
@ -139,6 +147,26 @@ module.exports = React.createClass({
|
|||||||
this.refs.scrollPanel.scrollToBottom();
|
this.refs.scrollPanel.scrollToBottom();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page up/down.
|
||||||
|
*
|
||||||
|
* mult: -1 to page up, +1 to page down
|
||||||
|
*/
|
||||||
|
scrollRelative: function(mult) {
|
||||||
|
if (this.refs.scrollPanel) {
|
||||||
|
this.refs.scrollPanel.scrollRelative(mult);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scroll up/down in response to a scroll key
|
||||||
|
*/
|
||||||
|
handleScrollKey: function(ev) {
|
||||||
|
if (this.refs.scrollPanel) {
|
||||||
|
this.refs.handleScrollKey(ev);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/* jump to the given event id.
|
/* jump to the given event id.
|
||||||
*
|
*
|
||||||
|
@ -1115,6 +1115,24 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called by the parent component when PageUp/Down/etc is pressed.
|
||||||
|
*
|
||||||
|
* We pass it down to the scroll panel.
|
||||||
|
*/
|
||||||
|
handleScrollKey: function(ev) {
|
||||||
|
var panel;
|
||||||
|
if(this.refs.searchResultsPanel) {
|
||||||
|
panel = this.refs.searchResultsPanel;
|
||||||
|
} else if(this.refs.messagePanel) {
|
||||||
|
panel = this.refs.messagePanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(panel) {
|
||||||
|
panel.handleScrollKey(ev);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// this has to be a proper method rather than an unnamed function,
|
// this has to be a proper method rather than an unnamed function,
|
||||||
// otherwise react calls it with null on each update.
|
// otherwise react calls it with null on each update.
|
||||||
_gatherTimelinePanelRef: function(r) {
|
_gatherTimelinePanelRef: function(r) {
|
||||||
|
@ -18,6 +18,7 @@ var React = require("react");
|
|||||||
var ReactDOM = require("react-dom");
|
var ReactDOM = require("react-dom");
|
||||||
var GeminiScrollbar = require('react-gemini-scrollbar');
|
var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||||
var q = require("q");
|
var q = require("q");
|
||||||
|
var KeyCode = require('../../KeyCode');
|
||||||
|
|
||||||
var DEBUG_SCROLL = false;
|
var DEBUG_SCROLL = false;
|
||||||
// var DEBUG_SCROLL = true;
|
// var DEBUG_SCROLL = true;
|
||||||
@ -326,6 +327,17 @@ module.exports = React.createClass({
|
|||||||
this.scrollState = {stuckAtBottom: true};
|
this.scrollState = {stuckAtBottom: true};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jump to the top of the content.
|
||||||
|
*/
|
||||||
|
scrollToTop: function() {
|
||||||
|
this._setScrollTop(0);
|
||||||
|
this._saveScrollState();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jump to the bottom of the content.
|
||||||
|
*/
|
||||||
scrollToBottom: function() {
|
scrollToBottom: function() {
|
||||||
// the easiest way to make sure that the scroll state is correctly
|
// the easiest way to make sure that the scroll state is correctly
|
||||||
// saved is to do the scroll, then save the updated state. (Calculating
|
// saved is to do the scroll, then save the updated state. (Calculating
|
||||||
@ -335,6 +347,45 @@ module.exports = React.createClass({
|
|||||||
this._saveScrollState();
|
this._saveScrollState();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page up/down.
|
||||||
|
*
|
||||||
|
* mult: -1 to page up, +1 to page down
|
||||||
|
*/
|
||||||
|
scrollRelative: function(mult) {
|
||||||
|
var scrollNode = this._getScrollNode();
|
||||||
|
var delta = mult * scrollNode.clientHeight * 0.5;
|
||||||
|
this._setScrollTop(scrollNode.scrollTop + delta);
|
||||||
|
this._saveScrollState();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scroll up/down in response to a scroll key
|
||||||
|
*/
|
||||||
|
handleScrollKey: function(ev) {
|
||||||
|
switch (ev.keyCode) {
|
||||||
|
case KeyCode.PAGE_UP:
|
||||||
|
this.scrollRelative(-1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KeyCode.PAGE_DOWN:
|
||||||
|
this.scrollRelative(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KeyCode.HOME:
|
||||||
|
if (ev.ctrlKey) {
|
||||||
|
this.scrollToTop();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KeyCode.END:
|
||||||
|
if (ev.ctrlKey) {
|
||||||
|
this.scrollToBottom();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/* Scroll the panel to bring the DOM node with the scroll token
|
/* Scroll the panel to bring the DOM node with the scroll token
|
||||||
* `scrollToken` into view.
|
* `scrollToken` into view.
|
||||||
*
|
*
|
||||||
|
@ -27,6 +27,7 @@ var dis = require("../../dispatcher");
|
|||||||
var ObjectUtils = require('../../ObjectUtils');
|
var ObjectUtils = require('../../ObjectUtils');
|
||||||
var Modal = require("../../Modal");
|
var Modal = require("../../Modal");
|
||||||
var UserActivity = require("../../UserActivity");
|
var UserActivity = require("../../UserActivity");
|
||||||
|
var KeyCode = require('../../KeyCode');
|
||||||
|
|
||||||
var PAGINATE_SIZE = 20;
|
var PAGINATE_SIZE = 20;
|
||||||
var INITIAL_SIZE = 20;
|
var INITIAL_SIZE = 20;
|
||||||
@ -520,6 +521,23 @@ var TimelinePanel = React.createClass({
|
|||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called by the parent component when PageUp/Down/etc is pressed.
|
||||||
|
*
|
||||||
|
* We pass it down to the scroll panel.
|
||||||
|
*/
|
||||||
|
handleScrollKey: function(ev) {
|
||||||
|
if (!this.refs.messagePanel) { return; }
|
||||||
|
|
||||||
|
// jump to the live timeline on ctrl-end, rather than the end of the
|
||||||
|
// timeline window.
|
||||||
|
if (ev.ctrlKey && ev.keyCode == KeyCode.END) {
|
||||||
|
this.jumpToLiveTimeline();
|
||||||
|
} else {
|
||||||
|
this.refs.messagePanel.handleScrollKey(ev);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_initTimeline: function(props) {
|
_initTimeline: function(props) {
|
||||||
var initialEvent = props.eventId;
|
var initialEvent = props.eventId;
|
||||||
var pixelOffset = props.eventPixelOffset;
|
var pixelOffset = props.eventPixelOffset;
|
||||||
|
@ -34,15 +34,7 @@ var MemberEntry = require("../../../TabCompleteEntries").MemberEntry;
|
|||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
|
|
||||||
var dis = require("../../../dispatcher");
|
var dis = require("../../../dispatcher");
|
||||||
var KeyCode = {
|
var KeyCode = require("../../../KeyCode");
|
||||||
ENTER: 13,
|
|
||||||
BACKSPACE: 8,
|
|
||||||
DELETE: 46,
|
|
||||||
TAB: 9,
|
|
||||||
SHIFT: 16,
|
|
||||||
UP: 38,
|
|
||||||
DOWN: 40
|
|
||||||
};
|
|
||||||
|
|
||||||
var TYPING_USER_TIMEOUT = 10000;
|
var TYPING_USER_TIMEOUT = 10000;
|
||||||
var TYPING_SERVER_TIMEOUT = 30000;
|
var TYPING_SERVER_TIMEOUT = 30000;
|
||||||
|
Loading…
Reference in New Issue
Block a user