Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
b8d7881663
11 changed files with 84 additions and 35 deletions
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 New Vector Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -15,7 +16,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* a selection of key codes, as used in KeyboardEvent.keyCode */
|
/* a selection of key codes, as used in KeyboardEvent.keyCode */
|
||||||
module.exports = {
|
export const KeyCode = {
|
||||||
BACKSPACE: 8,
|
BACKSPACE: 8,
|
||||||
TAB: 9,
|
TAB: 9,
|
||||||
ENTER: 13,
|
ENTER: 13,
|
||||||
|
@ -58,3 +59,12 @@ module.exports = {
|
||||||
KEY_Y: 89,
|
KEY_Y: 89,
|
||||||
KEY_Z: 90,
|
KEY_Z: 90,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function isOnlyCtrlOrCmdKeyEvent(ev) {
|
||||||
|
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||||
|
if (isMac) {
|
||||||
|
return ev.metaKey && !ev.altKey && !ev.ctrlKey && !ev.shiftKey;
|
||||||
|
} else {
|
||||||
|
return ev.ctrlKey && !ev.altKey && !ev.metaKey && !ev.shiftKey;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
||||||
import * as Matrix from 'matrix-js-sdk';
|
import * as Matrix from 'matrix-js-sdk';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import KeyCode from '../../KeyCode';
|
import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
|
||||||
import Notifier from '../../Notifier';
|
import Notifier from '../../Notifier';
|
||||||
import PageTypes from '../../PageTypes';
|
import PageTypes from '../../PageTypes';
|
||||||
import CallMediaHandler from '../../CallMediaHandler';
|
import CallMediaHandler from '../../CallMediaHandler';
|
||||||
|
@ -153,13 +153,7 @@ export default React.createClass({
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let handled = false;
|
let handled = false;
|
||||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev);
|
||||||
let ctrlCmdOnly;
|
|
||||||
if (isMac) {
|
|
||||||
ctrlCmdOnly = ev.metaKey && !ev.altKey && !ev.ctrlKey && !ev.shiftKey;
|
|
||||||
} else {
|
|
||||||
ctrlCmdOnly = ev.ctrlKey && !ev.altKey && !ev.metaKey && !ev.shiftKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ev.keyCode) {
|
switch (ev.keyCode) {
|
||||||
case KeyCode.UP:
|
case KeyCode.UP:
|
||||||
|
|
|
@ -41,7 +41,7 @@ const rate_limited_func = require('../../ratelimitedfunc');
|
||||||
const ObjectUtils = require('../../ObjectUtils');
|
const ObjectUtils = require('../../ObjectUtils');
|
||||||
const Rooms = require('../../Rooms');
|
const Rooms = require('../../Rooms');
|
||||||
|
|
||||||
import KeyCode from '../../KeyCode';
|
import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
|
||||||
|
|
||||||
import RoomViewStore from '../../stores/RoomViewStore';
|
import RoomViewStore from '../../stores/RoomViewStore';
|
||||||
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
||||||
|
@ -433,13 +433,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
onKeyDown: function(ev) {
|
onKeyDown: function(ev) {
|
||||||
let handled = false;
|
let handled = false;
|
||||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev);
|
||||||
let ctrlCmdOnly;
|
|
||||||
if (isMac) {
|
|
||||||
ctrlCmdOnly = ev.metaKey && !ev.altKey && !ev.ctrlKey && !ev.shiftKey;
|
|
||||||
} else {
|
|
||||||
ctrlCmdOnly = ev.ctrlKey && !ev.altKey && !ev.metaKey && !ev.shiftKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ev.keyCode) {
|
switch (ev.keyCode) {
|
||||||
case KeyCode.KEY_D:
|
case KeyCode.KEY_D:
|
||||||
|
|
|
@ -18,7 +18,7 @@ const React = require("react");
|
||||||
const ReactDOM = require("react-dom");
|
const ReactDOM = require("react-dom");
|
||||||
const GeminiScrollbar = require('react-gemini-scrollbar');
|
const GeminiScrollbar = require('react-gemini-scrollbar');
|
||||||
import Promise from 'bluebird';
|
import Promise from 'bluebird';
|
||||||
const KeyCode = require('../../KeyCode');
|
import { KeyCode } from '../../Keyboard';
|
||||||
|
|
||||||
const DEBUG_SCROLL = false;
|
const DEBUG_SCROLL = false;
|
||||||
// var DEBUG_SCROLL = true;
|
// var DEBUG_SCROLL = true;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import FilterStore from '../../stores/FilterStore';
|
||||||
import FlairStore from '../../stores/FlairStore';
|
import FlairStore from '../../stores/FlairStore';
|
||||||
import sdk from '../../index';
|
import sdk from '../../index';
|
||||||
import dis from '../../dispatcher';
|
import dis from '../../dispatcher';
|
||||||
|
import { isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
|
||||||
|
|
||||||
const TagTile = React.createClass({
|
const TagTile = React.createClass({
|
||||||
displayName: 'TagTile',
|
displayName: 'TagTile',
|
||||||
|
@ -46,6 +47,8 @@ const TagTile = React.createClass({
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'select_tag',
|
action: 'select_tag',
|
||||||
tag: this.props.groupProfile.groupId,
|
tag: this.props.groupProfile.groupId,
|
||||||
|
ctrlOrCmdKey: isOnlyCtrlOrCmdKeyEvent(e),
|
||||||
|
shiftKey: e.shiftKey,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -144,6 +147,10 @@ export default React.createClass({
|
||||||
const joinedGroupProfiles = await Promise.all(joinedGroupIds.map(
|
const joinedGroupProfiles = await Promise.all(joinedGroupIds.map(
|
||||||
(groupId) => FlairStore.getGroupProfileCached(this.context.matrixClient, groupId),
|
(groupId) => FlairStore.getGroupProfileCached(this.context.matrixClient, groupId),
|
||||||
));
|
));
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'all_tags',
|
||||||
|
tags: joinedGroupIds,
|
||||||
|
});
|
||||||
this.setState({joinedGroupProfiles});
|
this.setState({joinedGroupProfiles});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ const dis = require("../../dispatcher");
|
||||||
const ObjectUtils = require('../../ObjectUtils');
|
const ObjectUtils = require('../../ObjectUtils');
|
||||||
const Modal = require("../../Modal");
|
const Modal = require("../../Modal");
|
||||||
const UserActivity = require("../../UserActivity");
|
const UserActivity = require("../../UserActivity");
|
||||||
const KeyCode = require('../../KeyCode');
|
import { KeyCode } from '../../Keyboard';
|
||||||
|
|
||||||
const PAGINATE_SIZE = 20;
|
const PAGINATE_SIZE = 20;
|
||||||
const INITIAL_SIZE = 20;
|
const INITIAL_SIZE = 20;
|
||||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import * as KeyCode from '../../../KeyCode';
|
import { KeyCode } from '../../../Keyboard';
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import React from 'react';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import KeyCode from '../../../KeyCode';
|
import { KeyCode } from '../../../Keyboard';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
|
|
||||||
// The amount of time to wait for further changes to the input username before
|
// The amount of time to wait for further changes to the input username before
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import dis from '../../../dispatcher';
|
import dis from '../../../dispatcher';
|
||||||
import KeyCode from '../../../KeyCode';
|
import { KeyCode } from '../../../Keyboard';
|
||||||
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
|
|
|
@ -28,7 +28,7 @@ import Promise from 'bluebird';
|
||||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||||
import type {MatrixClient} from 'matrix-js-sdk/lib/matrix';
|
import type {MatrixClient} from 'matrix-js-sdk/lib/matrix';
|
||||||
import SlashCommands from '../../../SlashCommands';
|
import SlashCommands from '../../../SlashCommands';
|
||||||
import KeyCode from '../../../KeyCode';
|
import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../../Keyboard';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import { _t, _td } from '../../../languageHandler';
|
import { _t, _td } from '../../../languageHandler';
|
||||||
|
@ -105,13 +105,7 @@ export default class MessageComposerInput extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
static getKeyBinding(ev: SyntheticKeyboardEvent): string {
|
static getKeyBinding(ev: SyntheticKeyboardEvent): string {
|
||||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev);
|
||||||
let ctrlCmdOnly;
|
|
||||||
if (isMac) {
|
|
||||||
ctrlCmdOnly = ev.metaKey && !ev.altKey && !ev.ctrlKey && !ev.shiftKey;
|
|
||||||
} else {
|
|
||||||
ctrlCmdOnly = ev.ctrlKey && !ev.altKey && !ev.metaKey && !ev.shiftKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restrict a subset of key bindings to ONLY having ctrl/meta* pressed and
|
// Restrict a subset of key bindings to ONLY having ctrl/meta* pressed and
|
||||||
// importantly NOT having alt, shift, meta/ctrl* pressed. draft-js does not
|
// importantly NOT having alt, shift, meta/ctrl* pressed. draft-js does not
|
||||||
|
|
|
@ -18,7 +18,10 @@ import dis from '../dispatcher';
|
||||||
import Analytics from '../Analytics';
|
import Analytics from '../Analytics';
|
||||||
|
|
||||||
const INITIAL_STATE = {
|
const INITIAL_STATE = {
|
||||||
tags: [],
|
allTags: [],
|
||||||
|
selectedTags: [],
|
||||||
|
// Last selected tag when shift was not being pressed
|
||||||
|
anchorTag: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,15 +42,62 @@ class FilterStore extends Store {
|
||||||
|
|
||||||
__onDispatch(payload) {
|
__onDispatch(payload) {
|
||||||
switch (payload.action) {
|
switch (payload.action) {
|
||||||
case 'select_tag':
|
case 'all_tags' :
|
||||||
this._setState({
|
this._setState({
|
||||||
tags: [payload.tag],
|
allTags: payload.tags,
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
case 'select_tag': {
|
||||||
|
let newTags = [];
|
||||||
|
// Shift-click semantics
|
||||||
|
if (payload.shiftKey) {
|
||||||
|
// Select range of tags
|
||||||
|
let start = this._state.allTags.indexOf(this._state.anchorTag);
|
||||||
|
let end = this._state.allTags.indexOf(payload.tag);
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
if (start > end) {
|
||||||
|
const temp = start;
|
||||||
|
start = end;
|
||||||
|
end = temp;
|
||||||
|
}
|
||||||
|
newTags = payload.ctrlOrCmdKey ? this._state.selectedTags : [];
|
||||||
|
newTags = [...new Set(
|
||||||
|
this._state.allTags.slice(start, end + 1).concat(newTags),
|
||||||
|
)];
|
||||||
|
} else {
|
||||||
|
if (payload.ctrlOrCmdKey) {
|
||||||
|
// Toggle individual tag
|
||||||
|
if (this._state.selectedTags.includes(payload.tag)) {
|
||||||
|
newTags = this._state.selectedTags.filter((t) => t !== payload.tag);
|
||||||
|
} else {
|
||||||
|
newTags = [...this._state.selectedTags, payload.tag];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Select individual tag
|
||||||
|
newTags = [payload.tag];
|
||||||
|
}
|
||||||
|
// Only set the anchor tag if the tag was previously unselected, otherwise
|
||||||
|
// the next range starts with an unselected tag.
|
||||||
|
if (!this._state.selectedTags.includes(payload.tag)) {
|
||||||
|
this._setState({
|
||||||
|
anchorTag: payload.tag,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._setState({
|
||||||
|
selectedTags: newTags,
|
||||||
|
});
|
||||||
|
|
||||||
Analytics.trackEvent('FilterStore', 'select_tag');
|
Analytics.trackEvent('FilterStore', 'select_tag');
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'deselect_tags':
|
case 'deselect_tags':
|
||||||
this._setState({
|
this._setState({
|
||||||
tags: [],
|
selectedTags: [],
|
||||||
});
|
});
|
||||||
Analytics.trackEvent('FilterStore', 'deselect_tags');
|
Analytics.trackEvent('FilterStore', 'deselect_tags');
|
||||||
break;
|
break;
|
||||||
|
@ -55,7 +105,7 @@ class FilterStore extends Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
getSelectedTags() {
|
getSelectedTags() {
|
||||||
return this._state.tags;
|
return this._state.selectedTags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue