From baf320a86b1256588f2d3d977da8bfc164325724 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 16:17:37 +0530 Subject: [PATCH 01/38] Basic component with props added --- src/components/KeyboardShortcutsModal.js | 79 ++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/components/KeyboardShortcutsModal.js diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js new file mode 100644 index 000000000000..b63f9d0265a7 --- /dev/null +++ b/src/components/KeyboardShortcutsModal.js @@ -0,0 +1,79 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {View, Text} from 'react-native'; +import _ from 'underscore'; +import HeaderWithCloseButton from './HeaderWithCloseButton'; +import Modal from './Modal'; +import CONST from '../CONST'; +import styles from '../styles/styles'; +import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions'; +import withLocalize, {withLocalizePropTypes} from './withLocalize'; +import compose from '../libs/compose'; +import KeyboardShortcut from '../libs/KeyboardShortcut'; + +const propTypes = { + + /** Flag to visibility of shortcuts modal */ + isOpen: PropTypes.bool.isRequired, + + /** function to send the updated visibility flag to parent */ + toggleKeyboardShortcutModal: PropTypes.func.isRequired, + + /** prop to fetch screen width */ + ...windowDimensionsPropTypes, + + /** props to fetch translation functions */ + ...withLocalizePropTypes, + +}; + +const KeyboardShortcutsModal = ({ + isOpen, toggleKeyboardShortcutModal, isSmallScreenWidth, translate, +}) => { + const viewStyles = isSmallScreenWidth + ? [styles.imageModalImageCenterContainer] + : [styles.imageModalImageCenterContainer, {width: 650}]; + const shortcutMap = KeyboardShortcut.getKeyboardShortcutMap(); + + const shortcuts = []; + _.each(shortcutMap, (descriptionKey, key) => { + shortcuts.push({key, descriptionKey}); + }); + + + const renderRow = shortcut => ( + + + {shortcut.key} + + + {translate(`keyboardShortCutModal.shortcuts.${shortcut.descriptionKey}`)} + + + ); + + + return ( + toggleKeyboardShortcutModal(false)}> + + toggleKeyboardShortcutModal(false)} /> + Sub title + + + {shortcuts.map(shortcut => (renderRow(shortcut)))} + + + + + ); +}; + +KeyboardShortcutsModal.propTypes = propTypes; + +export default compose( + withWindowDimensions, + withLocalize, +)(KeyboardShortcutsModal); From fdf81af1d7947a022a2c7782b5d92d386d6818c6 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 16:35:13 +0530 Subject: [PATCH 02/38] Converted component to class component --- src/components/KeyboardShortcutsModal.js | 110 +++++++++++++---------- src/components/ScreenWrapper.js | 13 +++ 2 files changed, 76 insertions(+), 47 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index b63f9d0265a7..4c9bb88a0e0e 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import {View, Text} from 'react-native'; import _ from 'underscore'; import HeaderWithCloseButton from './HeaderWithCloseButton'; @@ -13,12 +12,6 @@ import KeyboardShortcut from '../libs/KeyboardShortcut'; const propTypes = { - /** Flag to visibility of shortcuts modal */ - isOpen: PropTypes.bool.isRequired, - - /** function to send the updated visibility flag to parent */ - toggleKeyboardShortcutModal: PropTypes.func.isRequired, - /** prop to fetch screen width */ ...windowDimensionsPropTypes, @@ -27,49 +20,72 @@ const propTypes = { }; -const KeyboardShortcutsModal = ({ - isOpen, toggleKeyboardShortcutModal, isSmallScreenWidth, translate, -}) => { - const viewStyles = isSmallScreenWidth - ? [styles.imageModalImageCenterContainer] - : [styles.imageModalImageCenterContainer, {width: 650}]; - const shortcutMap = KeyboardShortcut.getKeyboardShortcutMap(); - - const shortcuts = []; - _.each(shortcutMap, (descriptionKey, key) => { - shortcuts.push({key, descriptionKey}); - }); - - - const renderRow = shortcut => ( - - - {shortcut.key} - - - {translate(`keyboardShortCutModal.shortcuts.${shortcut.descriptionKey}`)} +class KeyboardShortcutsModal extends React.Component { + constructor(props) { + super(props); + + this.state = { + isOpen: false, + }; + } + + componentDidMount() { + this.unsubscribeShortCutModal = KeyboardShortcut.subscribe('?', () => { + this.toggleKeyboardShortcutModal(true); + }, [], false, 'openShortcutDialog'); + } + + /** + * Set flag for model visibility + * @param {Boolean} flag + */ + toggleKeyboardShortcutModal(flag) { + this.setState({isOpen: flag}); + } + + renderRow(shortcut) { + return ( + + + {shortcut.key} + + + {this.props.translate(`keyboardShortCutModal.shortcuts.${shortcut.descriptionKey}`)} + - - ); - - - return ( - toggleKeyboardShortcutModal(false)}> - - toggleKeyboardShortcutModal(false)} /> - Sub title + ); + } + + + render() { + const viewStyles = this.props.isSmallScreenWidth + ? [styles.imageModalImageCenterContainer] + : [styles.imageModalImageCenterContainer, {width: 650}]; + const shortcutMap = KeyboardShortcut.getKeyboardShortcutMap(); + + const shortcuts = []; + _.each(shortcutMap, (descriptionKey, key) => { + shortcuts.push({key, descriptionKey}); + }); + + return ( + this.toggleKeyboardShortcutModal(false)}> + + this.toggleKeyboardShortcutModal(false)} /> + {this.props.translate('keyboardShortCutModal.subtitle')} + + + {shortcuts.map(shortcut => (this.renderRow(shortcut)))} + - - {shortcuts.map(shortcut => (renderRow(shortcut)))} - - - - ); -}; + + ); + } +} KeyboardShortcutsModal.propTypes = propTypes; diff --git a/src/components/ScreenWrapper.js b/src/components/ScreenWrapper.js index 74f3c1cb733d..783c6d3c947f 100644 --- a/src/components/ScreenWrapper.js +++ b/src/components/ScreenWrapper.js @@ -7,6 +7,7 @@ import {SafeAreaInsetsContext} from 'react-native-safe-area-context'; import {withOnyx} from 'react-native-onyx'; import styles, {getSafeAreaPadding} from '../styles/styles'; import HeaderGap from './HeaderGap'; +import KeyboardShortcutsModal from './KeyboardShortcutsModal'; import KeyboardShortcut from '../libs/KeyboardShortcut'; import onScreenTransitionEnd from '../libs/onScreenTransitionEnd'; import Navigation from '../libs/Navigation/Navigation'; @@ -60,8 +61,10 @@ const defaultProps = { class ScreenWrapper extends React.Component { constructor(props) { super(props); + this.state = { didScreenTransitionEnd: false, + isKeyboardShortcutsModalOpen: false, }; } @@ -85,6 +88,14 @@ class ScreenWrapper extends React.Component { if (this.unsubscribeTransitionEnd) { this.unsubscribeTransitionEnd(); } + if (this.unsubscribeShortCutModal) { + this.unsubscribeShortCutModal(); + } + } + + + toggleKeyboardShortcutModal(flag) { + this.setState({isKeyboardShortcutsModalOpen: flag}); } render() { @@ -118,6 +129,8 @@ class ScreenWrapper extends React.Component { }) : this.props.children } + + ); }} From e00816c28f064986c53f4d05e59ae0a83ca2df93 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 16:35:26 +0530 Subject: [PATCH 03/38] Added mapper function to the keyboardshortcut lib --- src/libs/KeyboardShortcut/index.js | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index 1f82b4cab687..1bd361f14e61 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -1,6 +1,11 @@ import _ from 'underscore'; const events = {}; +const keyboardShortcutMap = {}; + +function getKeyboardShortcutMap() { + return keyboardShortcutMap; +} /** * Checks if an event for that key is configured and if so, runs it. @@ -107,20 +112,43 @@ function unsubscribe(key) { events[keyCode].pop(); } +/** + * Add key to the shortcut map + * + * @param {String} key The key to watch, i.e. 'K' or 'Escape' + * @param {String|String[]} modifiers Can either be shift or control + * @param {String} descriptionKey Translation key for shortcut description + */ +function addKeyToMap(key, modifiers, descriptionKey) { + let shortcutKey = [key]; + if (typeof modifiers === 'string') { + shortcutKey.unshift(modifiers); + } else if (Array.isArray(modifiers)) { + shortcutKey = [...modifiers, ...shortcutKey]; + } + + shortcutKey = shortcutKey.join(' + '); + keyboardShortcutMap[shortcutKey] = descriptionKey; +} + + /** * Subscribes to a keyboard event. * @param {String} key The key to watch, i.e. 'K' or 'Escape' * @param {Function} callback The callback to call * @param {String|Array} modifiers Can either be shift or control * @param {Boolean} captureOnInputs Should we capture the event on inputs too? + * @param {String} descriptionKey Translation key for shortcut description * @returns {Function} clean up method */ -function subscribe(key, callback, modifiers = 'shift', captureOnInputs = false) { +function subscribe(key, callback, modifiers = 'shift', captureOnInputs = false, descriptionKey) { const keyCode = getKeyCode(key); if (events[keyCode] === undefined) { events[keyCode] = []; } events[keyCode].push({callback, modifiers: _.isArray(modifiers) ? modifiers : [modifiers], captureOnInputs}); + + addKeyToMap(key, modifiers, descriptionKey); return () => unsubscribe(key); } @@ -137,6 +165,7 @@ function subscribe(key, callback, modifiers = 'shift', captureOnInputs = false) */ const KeyboardShortcut = { subscribe, + getKeyboardShortcutMap, }; export default KeyboardShortcut; From 28855fbef8492396ce988b52e109dedcf4d9ff73 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 16:35:52 +0530 Subject: [PATCH 04/38] Translation files --- src/languages/en.js | 4 ++++ src/languages/es.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/languages/en.js b/src/languages/en.js index 097d9bb5724c..d869886461b4 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -761,4 +761,8 @@ export default { emojiPicker: { skinTonePickerLabel: 'Change default skin tone', }, + keyboardShortCutModal: { + title: 'Keyboard Shortcuts', + subtitle: 'Do you expense reports faster with these handy keyboard shortcuts', + }, }; diff --git a/src/languages/es.js b/src/languages/es.js index 37eb855bbf3c..65ab280429ef 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -763,4 +763,8 @@ export default { emojiPicker: { skinTonePickerLabel: 'Elige el tono de piel por defecto', }, + keyboardShortCutModal: { + title: 'Keyboard Shortcuts', + subtitle: 'Do you expense reports faster with these handy keyboard shortcuts', + }, }; From cb5493818a9d858053ca6d1bdb46a6d42b422d82 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 16:47:15 +0530 Subject: [PATCH 05/38] Removed modal props from ScreenWrapper --- src/components/ScreenWrapper.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/components/ScreenWrapper.js b/src/components/ScreenWrapper.js index 783c6d3c947f..a8605ff3dc8b 100644 --- a/src/components/ScreenWrapper.js +++ b/src/components/ScreenWrapper.js @@ -64,7 +64,6 @@ class ScreenWrapper extends React.Component { this.state = { didScreenTransitionEnd: false, - isKeyboardShortcutsModalOpen: false, }; } @@ -88,14 +87,6 @@ class ScreenWrapper extends React.Component { if (this.unsubscribeTransitionEnd) { this.unsubscribeTransitionEnd(); } - if (this.unsubscribeShortCutModal) { - this.unsubscribeShortCutModal(); - } - } - - - toggleKeyboardShortcutModal(flag) { - this.setState({isKeyboardShortcutsModalOpen: flag}); } render() { @@ -129,7 +120,7 @@ class ScreenWrapper extends React.Component { }) : this.props.children } - + ); From a6c28bd5f5b5fa63ecc087abdd8676050305b865 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 17:24:41 +0530 Subject: [PATCH 06/38] Modified the shortcut trigger logic to modal --- src/components/KeyboardShortcutsModal.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 4c9bb88a0e0e..ff80f8e8f718 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -9,6 +9,7 @@ import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimen import withLocalize, {withLocalizePropTypes} from './withLocalize'; import compose from '../libs/compose'; import KeyboardShortcut from '../libs/KeyboardShortcut'; +import getOperatingSystem from '../libs/getOperatingSystem'; const propTypes = { @@ -20,7 +21,7 @@ const propTypes = { }; -class KeyboardShortcutsModal extends React.Component { +class KeyboardShortcutsModal extends React.PureComponent { constructor(props) { super(props); @@ -30,11 +31,22 @@ class KeyboardShortcutsModal extends React.Component { } componentDidMount() { + let shortcutModifiers = ['control']; + if (getOperatingSystem() === CONST.OS.MAC_OS) { + shortcutModifiers = ['meta']; + } this.unsubscribeShortCutModal = KeyboardShortcut.subscribe('?', () => { this.toggleKeyboardShortcutModal(true); - }, [], false, 'openShortcutDialog'); + }, shortcutModifiers, false, 'openShortcutDialog'); } + componentWillUnmount() { + if (this.unsubscribeShortCutModal) { + this.unsubscribeShortCutModal(); + } + } + + /** * Set flag for model visibility * @param {Boolean} flag @@ -69,7 +81,7 @@ class KeyboardShortcutsModal extends React.Component { }); return ( - this.toggleKeyboardShortcutModal(false)}> + this.toggleKeyboardShortcutModal(false)}> this.toggleKeyboardShortcutModal(false)} /> {this.props.translate('keyboardShortCutModal.subtitle')} From 6bad7759cb9a8c5094e292d57bc89c3d728a5bb1 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 17:25:48 +0530 Subject: [PATCH 07/38] Added keys for existing shortcuts --- src/components/ScreenWrapper.js | 2 +- src/languages/en.js | 6 ++++++ src/languages/es.js | 6 ++++++ src/libs/KeyboardShortcut/index.js | 2 ++ src/libs/Navigation/AppNavigator/AuthScreens.js | 4 ++-- 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/components/ScreenWrapper.js b/src/components/ScreenWrapper.js index a8605ff3dc8b..3d5e0d415e9a 100644 --- a/src/components/ScreenWrapper.js +++ b/src/components/ScreenWrapper.js @@ -72,7 +72,7 @@ class ScreenWrapper extends React.Component { if (!this.props.modal.willAlertModalBecomeVisible) { Navigation.dismissModal(); } - }, [], true); + }, [], true, 'escape'); this.unsubscribeTransitionEnd = onScreenTransitionEnd(this.props.navigation, () => { this.setState({didScreenTransitionEnd: true}); diff --git a/src/languages/en.js b/src/languages/en.js index d869886461b4..0d3338ae4846 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -764,5 +764,11 @@ export default { keyboardShortCutModal: { title: 'Keyboard Shortcuts', subtitle: 'Do you expense reports faster with these handy keyboard shortcuts', + shortcuts: { + openShortcutDialog: 'Opens the keyboard shortcuts dialog', + escape: 'Escape Dialogs', + search: 'Open search dialog', + newGroup: 'New group screen', + }, }, }; diff --git a/src/languages/es.js b/src/languages/es.js index 65ab280429ef..2a0b38d4b128 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -766,5 +766,11 @@ export default { keyboardShortCutModal: { title: 'Keyboard Shortcuts', subtitle: 'Do you expense reports faster with these handy keyboard shortcuts', + shortcuts: { + openShortcutDialog: 'Opens the keyboard shortcuts dialog', + escape: 'Escape Dialogs', + search: 'Open search dialog', + newGroup: 'New group screen', + }, }, }; diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index 1bd361f14e61..1377aaccdcc3 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -97,6 +97,8 @@ function getKeyCode(key) { return 13; case 'Escape': return 27; + case '?': + return 191; default: return key.charCodeAt(0); } diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 73a390a7967d..6a088c9f58a3 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -206,10 +206,10 @@ class AuthScreens extends React.Component { // based on the key modifiers pressed and the operating system this.unsubscribeSearchShortcut = KeyboardShortcut.subscribe('K', () => { Navigation.navigate(ROUTES.SEARCH); - }, searchShortcutModifiers, true); + }, searchShortcutModifiers, true, 'search'); this.unsubscribeGroupShortcut = KeyboardShortcut.subscribe('K', () => { Navigation.navigate(ROUTES.NEW_GROUP); - }, groupShortcutModifiers, true); + }, groupShortcutModifiers, true, 'newGroup'); } shouldComponentUpdate(nextProps) { From 290acb890e6284abf627028a706ebf849b575881 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 17:48:37 +0530 Subject: [PATCH 08/38] Styling updates for container --- src/components/KeyboardShortcutsModal.js | 24 ++++++++++-------------- src/styles/styles.js | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index ff80f8e8f718..d41147f08b34 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -4,7 +4,7 @@ import _ from 'underscore'; import HeaderWithCloseButton from './HeaderWithCloseButton'; import Modal from './Modal'; import CONST from '../CONST'; -import styles from '../styles/styles'; +import styles, {getKeyboardShortcutModalStyle} from '../styles/styles'; import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import compose from '../libs/compose'; @@ -70,26 +70,22 @@ class KeyboardShortcutsModal extends React.PureComponent { render() { - const viewStyles = this.props.isSmallScreenWidth - ? [styles.imageModalImageCenterContainer] - : [styles.imageModalImageCenterContainer, {width: 650}]; const shortcutMap = KeyboardShortcut.getKeyboardShortcutMap(); - const shortcuts = []; _.each(shortcutMap, (descriptionKey, key) => { shortcuts.push({key, descriptionKey}); }); return ( - this.toggleKeyboardShortcutModal(false)}> - - this.toggleKeyboardShortcutModal(false)} /> - {this.props.translate('keyboardShortCutModal.subtitle')} - - + this.toggleKeyboardShortcutModal(false)} + > + this.toggleKeyboardShortcutModal(false)} /> + {this.props.translate('keyboardShortCutModal.subtitle')} + + {shortcuts.map(shortcut => (this.renderRow(shortcut)))} diff --git a/src/styles/styles.js b/src/styles/styles.js index 4488a4643d4a..1603579e315a 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2108,6 +2108,13 @@ const styles = { fontFamily: fontFamily.GTA, flex: 1, }, + + keyboardShortcutTableContainer: { + width: '100%', + borderColor: 'grey', + borderRadius: 8, + borderWidth: 1, + }, }; const baseCodeTagStyles = { @@ -2202,6 +2209,21 @@ const webViewStyles = { }, }; +/** + * Styles for the keyboard shortcut modal container based on screen size + * + * @param {Boolean} isSmallScreenWidth + * @returns {Object} + */ +function getKeyboardShortcutModalStyle(isSmallScreenWidth) { + return { + width: isSmallScreenWidth ? '100%' : '90%', + alignItems: 'center', + flex: 1, + justifyContent: 'center', + }; +} + /** * Takes safe area insets and returns padding to use for a View * @@ -2484,4 +2506,5 @@ export { getModalPaddingStyles, getFontFamilyMonospace, getEmojiPickerStyle, + getKeyboardShortcutModalStyle, }; From f31f5ed47dd7dac26919727e24b232004e740312 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 17:53:32 +0530 Subject: [PATCH 09/38] Key handling for cmd --- src/libs/KeyboardShortcut/index.js | 13 +++++++++++++ src/libs/KeyboardShortcut/index.native.js | 1 + 2 files changed, 14 insertions(+) diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index 1377aaccdcc3..197d1d467fb9 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -129,6 +129,19 @@ function addKeyToMap(key, modifiers, descriptionKey) { shortcutKey = [...modifiers, ...shortcutKey]; } + shortcutKey = shortcutKey.map((modifierKey) => { + switch (modifierKey) { + case 'control': + return 'Ctrl'; + case 'meta': + return 'Cmd'; + case 'shift': + return 'Shift'; + default: + return modifierKey; + } + }); + shortcutKey = shortcutKey.join(' + '); keyboardShortcutMap[shortcutKey] = descriptionKey; } diff --git a/src/libs/KeyboardShortcut/index.native.js b/src/libs/KeyboardShortcut/index.native.js index d2f7c592df0b..8b331bc17bdb 100644 --- a/src/libs/KeyboardShortcut/index.native.js +++ b/src/libs/KeyboardShortcut/index.native.js @@ -7,6 +7,7 @@ const KeyboardShortcut = { return () => {}; }, unsubscribe() {}, + getKeyboardShortcutMap() {}, }; export default KeyboardShortcut; From 2b6e3198432bd9370771960c57ecdb973219638e Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 18:10:31 +0530 Subject: [PATCH 10/38] Moved styling to style.js --- src/components/KeyboardShortcutsModal.js | 16 +++++++++------- src/styles/styles.js | 21 ++++++++++++++++++--- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index d41147f08b34..c730fd861065 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -57,8 +57,8 @@ class KeyboardShortcutsModal extends React.PureComponent { renderRow(shortcut) { return ( - - + + {shortcut.key} @@ -83,12 +83,14 @@ class KeyboardShortcutsModal extends React.PureComponent { onClose={() => this.toggleKeyboardShortcutModal(false)} > this.toggleKeyboardShortcutModal(false)} /> - {this.props.translate('keyboardShortCutModal.subtitle')} - - - {shortcuts.map(shortcut => (this.renderRow(shortcut)))} - + + {this.props.translate('keyboardShortCutModal.subtitle')} + + + {shortcuts.map(shortcut => (this.renderRow(shortcut)))} + + ); diff --git a/src/styles/styles.js b/src/styles/styles.js index 1603579e315a..5915decc4e45 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2110,10 +2110,26 @@ const styles = { }, keyboardShortcutTableContainer: { + display: 'flex', width: '100%', - borderColor: 'grey', - borderRadius: 8, + borderColor: colors.gray3, + borderWidth: 1, + height: 'auto', + }, + + keyboardShortcutTableRow: { + flex: 1, + flexDirection: 'row', + borderColor: colors.gray3, borderWidth: 1, + maxHeight: 40, + alignSelf: 'stretch', + borderBottomWidth: 0, + }, + + keyboardShortcutTablePrefix: { + width: '30%', + backgroundColor: colors.gray2, }, }; @@ -2220,7 +2236,6 @@ function getKeyboardShortcutModalStyle(isSmallScreenWidth) { width: isSmallScreenWidth ? '100%' : '90%', alignItems: 'center', flex: 1, - justifyContent: 'center', }; } From 32622ab375be683695bf6f29475ae5f995244bd4 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 18:12:26 +0530 Subject: [PATCH 11/38] Changed border styling --- src/styles/styles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index 5915decc4e45..2393fd71a0e4 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2113,8 +2113,8 @@ const styles = { display: 'flex', width: '100%', borderColor: colors.gray3, - borderWidth: 1, height: 'auto', + borderBottomWidth: 1, }, keyboardShortcutTableRow: { From 2e0d4c7cbf2c8a64011f353c0fbabbd9d95ac52f Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 29 Oct 2021 18:27:39 +0530 Subject: [PATCH 12/38] Added spanish translations --- src/languages/es.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/languages/es.js b/src/languages/es.js index 2a0b38d4b128..8dbc7b6ad397 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -764,13 +764,13 @@ export default { skinTonePickerLabel: 'Elige el tono de piel por defecto', }, keyboardShortCutModal: { - title: 'Keyboard Shortcuts', - subtitle: 'Do you expense reports faster with these handy keyboard shortcuts', + title: 'Atajos de teclado', + subtitle: '¿Realiza informes de gastos más rápido con estos prácticos atajos de teclado?', shortcuts: { - openShortcutDialog: 'Opens the keyboard shortcuts dialog', - escape: 'Escape Dialogs', - search: 'Open search dialog', - newGroup: 'New group screen', + openShortcutDialog: 'Abre el cuadro de diálogo de métodos abreviados de teclado', + escape: 'Diálogos de escape', + search: 'Abrir diálogo de búsqueda', + newGroup: 'Nueva pantalla de grupo', }, }, }; From 20961968d96874e8eb67617ed2e6f60a35188e4e Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Wed, 3 Nov 2021 19:17:57 +0530 Subject: [PATCH 13/38] Added styling options for modal --- src/components/KeyboardShortcutsModal.js | 3 ++- src/components/Modal/BaseModal.js | 1 + src/components/Modal/modalPropTypes.js | 5 +++++ src/styles/getModalStyles.js | 4 +++- src/styles/styles.js | 8 ++++++++ 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index c730fd861065..27453fe4b935 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -80,10 +80,11 @@ class KeyboardShortcutsModal extends React.PureComponent { this.toggleKeyboardShortcutModal(false)} > this.toggleKeyboardShortcutModal(false)} /> - + {this.props.translate('keyboardShortCutModal.subtitle')} diff --git a/src/components/Modal/BaseModal.js b/src/components/Modal/BaseModal.js index 72f27a080a8a..2f5452b1a7d6 100644 --- a/src/components/Modal/BaseModal.js +++ b/src/components/Modal/BaseModal.js @@ -70,6 +70,7 @@ class BaseModal extends PureComponent { isSmallScreenWidth: this.props.isSmallScreenWidth, }, this.props.popoverAnchorPosition, + this.props.containerStyle, ); return ( { +export default (type, windowDimensions, popoverAnchorPosition = {}, containerStyle = {}) => { const {isSmallScreenWidth, windowWidth} = windowDimensions; let modalStyle = { @@ -206,6 +206,8 @@ export default (type, windowDimensions, popoverAnchorPosition = {}) => { animationOut = 'slideOutDown'; } + modalContainerStyle = {...modalContainerStyle, ...containerStyle}; + return { modalStyle, modalContainerStyle, diff --git a/src/styles/styles.js b/src/styles/styles.js index 2393fd71a0e4..fbf634ff9c9d 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2109,6 +2109,12 @@ const styles = { flex: 1, }, + keyboardShortcutModalContainer: { + maxWidth: 600, + maxHeight: '100%', + flex: '0 0 auto', + }, + keyboardShortcutTableContainer: { display: 'flex', width: '100%', @@ -2236,6 +2242,8 @@ function getKeyboardShortcutModalStyle(isSmallScreenWidth) { width: isSmallScreenWidth ? '100%' : '90%', alignItems: 'center', flex: 1, + height: 'auto', + maxHeight: '100%', }; } From 18fbadf5af04c7189c3c8965c97fcc7554557653 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Wed, 3 Nov 2021 19:28:40 +0530 Subject: [PATCH 14/38] Added borderRadius to the table --- src/components/KeyboardShortcutsModal.js | 17 ++++++++++++++--- src/styles/styles.js | 14 +++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 27453fe4b935..c4cca6bd64c6 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -55,9 +55,16 @@ class KeyboardShortcutsModal extends React.PureComponent { this.setState({isOpen: flag}); } - renderRow(shortcut) { + renderRow(shortcut, isFirstRow, isLastRow) { return ( - + {shortcut.key} @@ -88,7 +95,11 @@ class KeyboardShortcutsModal extends React.PureComponent { {this.props.translate('keyboardShortCutModal.subtitle')} - {shortcuts.map(shortcut => (this.renderRow(shortcut)))} + {shortcuts.map((shortcut, index) => { + const isFirstRow = index === 0; + const isLastRow = index === shortcuts.length - 1; + return this.renderRow(shortcut, isFirstRow, isLastRow); + })} diff --git a/src/styles/styles.js b/src/styles/styles.js index fbf634ff9c9d..cd78df1032be 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2113,6 +2113,7 @@ const styles = { maxWidth: 600, maxHeight: '100%', flex: '0 0 auto', + fontFamily: fontFamily.GTA, }, keyboardShortcutTableContainer: { @@ -2135,7 +2136,18 @@ const styles = { keyboardShortcutTablePrefix: { width: '30%', - backgroundColor: colors.gray2, + borderRightWidth: 1, + borderColor: colors.gray3, + }, + + keyboardShortcutTableFirstRow: { + borderTopLeftRadius: variables.componentBorderRadius, + borderTopRightRadius: variables.componentBorderRadius, + }, + + keyboardShortcutTableLastRow: { + borderBottomLeftRadius: variables.componentBorderRadius, + borderBottomRightRadius: variables.componentBorderRadius, }, }; From 640687d4040482e5512a4acfdfa21eca37c73b57 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Wed, 3 Nov 2021 19:43:33 +0530 Subject: [PATCH 15/38] Fixed border styling for the table --- src/components/KeyboardShortcutsModal.js | 6 ++---- src/styles/styles.js | 14 ++++---------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index c4cca6bd64c6..94da439927de 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -55,13 +55,12 @@ class KeyboardShortcutsModal extends React.PureComponent { this.setState({isOpen: flag}); } - renderRow(shortcut, isFirstRow, isLastRow) { + renderRow(shortcut, isFirstRow) { return ( @@ -97,8 +96,7 @@ class KeyboardShortcutsModal extends React.PureComponent { {shortcuts.map((shortcut, index) => { const isFirstRow = index === 0; - const isLastRow = index === shortcuts.length - 1; - return this.renderRow(shortcut, isFirstRow, isLastRow); + return this.renderRow(shortcut, isFirstRow); })} diff --git a/src/styles/styles.js b/src/styles/styles.js index cd78df1032be..b79656dccc6b 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2121,17 +2121,17 @@ const styles = { width: '100%', borderColor: colors.gray3, height: 'auto', - borderBottomWidth: 1, + borderRadius: variables.componentBorderRadius, + borderWidth: 1, }, keyboardShortcutTableRow: { flex: 1, flexDirection: 'row', borderColor: colors.gray3, - borderWidth: 1, maxHeight: 40, alignSelf: 'stretch', - borderBottomWidth: 0, + borderTopWidth: 1, }, keyboardShortcutTablePrefix: { @@ -2141,13 +2141,7 @@ const styles = { }, keyboardShortcutTableFirstRow: { - borderTopLeftRadius: variables.componentBorderRadius, - borderTopRightRadius: variables.componentBorderRadius, - }, - - keyboardShortcutTableLastRow: { - borderBottomLeftRadius: variables.componentBorderRadius, - borderBottomRightRadius: variables.componentBorderRadius, + borderTopWidth: 0, }, }; From c18e2a463e96d2ea6019fdcb855415ce9e8a4a64 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Wed, 3 Nov 2021 20:14:14 +0530 Subject: [PATCH 16/38] Removed height hardcoding --- src/styles/styles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index b79656dccc6b..b34e714b8b82 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2129,7 +2129,7 @@ const styles = { flex: 1, flexDirection: 'row', borderColor: colors.gray3, - maxHeight: 40, + flexBasis: 'auto', alignSelf: 'stretch', borderTopWidth: 1, }, From ea2a41f9b9402900ebe72a43904101822a4ae618 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Sun, 7 Nov 2021 14:05:32 +0530 Subject: [PATCH 17/38] Allow modal to open in input focus as well --- src/components/KeyboardShortcutsModal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 94da439927de..ded156921705 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -37,7 +37,7 @@ class KeyboardShortcutsModal extends React.PureComponent { } this.unsubscribeShortCutModal = KeyboardShortcut.subscribe('?', () => { this.toggleKeyboardShortcutModal(true); - }, shortcutModifiers, false, 'openShortcutDialog'); + }, shortcutModifiers, true, 'openShortcutDialog'); } componentWillUnmount() { From e39b19893e98d79b989126f35829b81806c99ce1 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Sun, 7 Nov 2021 14:11:31 +0530 Subject: [PATCH 18/38] Updated copy for the modal subtitle --- src/languages/en.js | 2 +- src/languages/es.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index ea3a3b01c372..6d894fed97dc 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -776,7 +776,7 @@ export default { }, keyboardShortCutModal: { title: 'Keyboard Shortcuts', - subtitle: 'Do you expense reports faster with these handy keyboard shortcuts', + subtitle: 'Save time with these handy keyboard shortcuts:', shortcuts: { openShortcutDialog: 'Opens the keyboard shortcuts dialog', escape: 'Escape Dialogs', diff --git a/src/languages/es.js b/src/languages/es.js index dcd24c152b70..9bbb20652833 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -778,7 +778,7 @@ export default { }, keyboardShortCutModal: { title: 'Atajos de teclado', - subtitle: '¿Realiza informes de gastos más rápido con estos prácticos atajos de teclado?', + subtitle: 'Ahorra tiempo con estos atajos de teclado:', shortcuts: { openShortcutDialog: 'Abre el cuadro de diálogo de métodos abreviados de teclado', escape: 'Diálogos de escape', From 77c93815f2eafcc1dcef943ed8285b72a4d56904 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Mon, 8 Nov 2021 21:14:12 +0530 Subject: [PATCH 19/38] Code cleanup --- src/components/KeyboardShortcutsModal.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index ded156921705..c103527fc9ad 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -1,7 +1,8 @@ import React from 'react'; -import {View, Text} from 'react-native'; +import {View} from 'react-native'; import _ from 'underscore'; import HeaderWithCloseButton from './HeaderWithCloseButton'; +import Text from './Text'; import Modal from './Modal'; import CONST from '../CONST'; import styles, {getKeyboardShortcutModalStyle} from '../styles/styles'; @@ -12,13 +13,11 @@ import KeyboardShortcut from '../libs/KeyboardShortcut'; import getOperatingSystem from '../libs/getOperatingSystem'; const propTypes = { - /** prop to fetch screen width */ ...windowDimensionsPropTypes, /** props to fetch translation functions */ ...withLocalizePropTypes, - }; class KeyboardShortcutsModal extends React.PureComponent { From 111edbc4d8c91d19d2e187631b3bceaaeeb767fb Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Mon, 8 Nov 2021 21:14:27 +0530 Subject: [PATCH 20/38] Moved object to map to Keyboardshortcut lib --- src/components/KeyboardShortcutsModal.js | 8 ++------ src/libs/KeyboardShortcut/index.js | 7 ++++++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index c103527fc9ad..bb207cb46caa 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -75,11 +75,7 @@ class KeyboardShortcutsModal extends React.PureComponent { render() { - const shortcutMap = KeyboardShortcut.getKeyboardShortcutMap(); - const shortcuts = []; - _.each(shortcutMap, (descriptionKey, key) => { - shortcuts.push({key, descriptionKey}); - }); + const shortcuts = KeyboardShortcut.getKeyboardShortcutMap(); return ( {this.props.translate('keyboardShortCutModal.subtitle')} - {shortcuts.map((shortcut, index) => { + {_.map(shortcuts, (shortcut, index) => { const isFirstRow = index === 0; return this.renderRow(shortcut, isFirstRow); })} diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index 197d1d467fb9..12f73365ae6d 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -4,7 +4,12 @@ const events = {}; const keyboardShortcutMap = {}; function getKeyboardShortcutMap() { - return keyboardShortcutMap; + const shortcuts = []; + _.each(keyboardShortcutMap, (descriptionKey, key) => { + shortcuts.push({key, descriptionKey}); + }); + + return shortcuts; } /** From 06e42c4adc748513f6ef1828dd0da2832d38fe3d Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Mon, 8 Nov 2021 21:16:24 +0530 Subject: [PATCH 21/38] Reordered params for KeyboardShortcut.subscribe --- src/components/Button.js | 2 +- src/components/KeyboardShortcutsModal.js | 2 +- src/components/ScreenWrapper.js | 2 +- src/libs/KeyboardShortcut/index.js | 4 ++-- src/libs/Navigation/AppNavigator/AuthScreens.js | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/Button.js b/src/components/Button.js index 3038e0c64f21..d97649da6107 100644 --- a/src/components/Button.js +++ b/src/components/Button.js @@ -95,7 +95,7 @@ class Button extends Component { if (!this.props.isDisabled && !this.props.isLoading) { this.props.onPress(); } - }, [], true); + }, null, [], true); } componentWillUnmount() { diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index bb207cb46caa..c236597c7cef 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -36,7 +36,7 @@ class KeyboardShortcutsModal extends React.PureComponent { } this.unsubscribeShortCutModal = KeyboardShortcut.subscribe('?', () => { this.toggleKeyboardShortcutModal(true); - }, shortcutModifiers, true, 'openShortcutDialog'); + }, 'openShortcutDialog', shortcutModifiers, true); } componentWillUnmount() { diff --git a/src/components/ScreenWrapper.js b/src/components/ScreenWrapper.js index 3d5e0d415e9a..8a93eddda730 100644 --- a/src/components/ScreenWrapper.js +++ b/src/components/ScreenWrapper.js @@ -72,7 +72,7 @@ class ScreenWrapper extends React.Component { if (!this.props.modal.willAlertModalBecomeVisible) { Navigation.dismissModal(); } - }, [], true, 'escape'); + }, 'escape', [], true); this.unsubscribeTransitionEnd = onScreenTransitionEnd(this.props.navigation, () => { this.setState({didScreenTransitionEnd: true}); diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index 12f73365ae6d..dbc58da7ae13 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -156,12 +156,12 @@ function addKeyToMap(key, modifiers, descriptionKey) { * Subscribes to a keyboard event. * @param {String} key The key to watch, i.e. 'K' or 'Escape' * @param {Function} callback The callback to call + * @param {String} descriptionKey Translation key for shortcut description * @param {String|Array} modifiers Can either be shift or control * @param {Boolean} captureOnInputs Should we capture the event on inputs too? - * @param {String} descriptionKey Translation key for shortcut description * @returns {Function} clean up method */ -function subscribe(key, callback, modifiers = 'shift', captureOnInputs = false, descriptionKey) { +function subscribe(key, callback, descriptionKey, modifiers = 'shift', captureOnInputs = false) { const keyCode = getKeyCode(key); if (events[keyCode] === undefined) { events[keyCode] = []; diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index edc89a54b7ed..0d9970e6e94f 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -200,10 +200,10 @@ class AuthScreens extends React.Component { // based on the key modifiers pressed and the operating system this.unsubscribeSearchShortcut = KeyboardShortcut.subscribe('K', () => { Navigation.navigate(ROUTES.SEARCH); - }, searchShortcutModifiers, true, 'search'); + }, 'search', searchShortcutModifiers, true); this.unsubscribeGroupShortcut = KeyboardShortcut.subscribe('K', () => { Navigation.navigate(ROUTES.NEW_GROUP); - }, groupShortcutModifiers, true, 'newGroup'); + }, 'newGroup', groupShortcutModifiers, true); } shouldComponentUpdate(nextProps) { From 1018fb58e18825ed390db482b6f4a6327e2e1751 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Mon, 8 Nov 2021 21:23:06 +0530 Subject: [PATCH 22/38] Styling fixes --- src/components/KeyboardShortcutsModal.js | 6 ++--- src/styles/styles.js | 31 ++++++++---------------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index c236597c7cef..804315c9682b 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -5,7 +5,7 @@ import HeaderWithCloseButton from './HeaderWithCloseButton'; import Text from './Text'; import Modal from './Modal'; import CONST from '../CONST'; -import styles, {getKeyboardShortcutModalStyle} from '../styles/styles'; +import styles from '../styles/styles'; import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import compose from '../libs/compose'; @@ -59,6 +59,7 @@ class KeyboardShortcutsModal extends React.PureComponent { this.toggleKeyboardShortcutModal(false)} /> {this.props.translate('keyboardShortCutModal.subtitle')} - + {_.map(shortcuts, (shortcut, index) => { const isFirstRow = index === 0; return this.renderRow(shortcut, isFirstRow); })} - diff --git a/src/styles/styles.js b/src/styles/styles.js index 355fc6eeb4da..94e9c9453ccf 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2090,13 +2090,19 @@ const styles = { maxWidth: 600, maxHeight: '100%', flex: '0 0 auto', - fontFamily: fontFamily.GTA, + }, + + keyboardShortcutTableWrapper: { + alignItems: 'center', + flex: 1, + height: 'auto', + maxHeight: '100%', }, keyboardShortcutTableContainer: { display: 'flex', width: '100%', - borderColor: colors.gray3, + borderColor: themeColors.border, height: 'auto', borderRadius: variables.componentBorderRadius, borderWidth: 1, @@ -2105,7 +2111,7 @@ const styles = { keyboardShortcutTableRow: { flex: 1, flexDirection: 'row', - borderColor: colors.gray3, + borderColor: themeColors.border, flexBasis: 'auto', alignSelf: 'stretch', borderTopWidth: 1, @@ -2114,7 +2120,7 @@ const styles = { keyboardShortcutTablePrefix: { width: '30%', borderRightWidth: 1, - borderColor: colors.gray3, + borderColor: themeColors.border, }, keyboardShortcutTableFirstRow: { @@ -2213,22 +2219,6 @@ const webViewStyles = { }, }; -/** - * Styles for the keyboard shortcut modal container based on screen size - * - * @param {Boolean} isSmallScreenWidth - * @returns {Object} - */ -function getKeyboardShortcutModalStyle(isSmallScreenWidth) { - return { - width: isSmallScreenWidth ? '100%' : '90%', - alignItems: 'center', - flex: 1, - height: 'auto', - maxHeight: '100%', - }; -} - /** * Takes safe area insets and returns padding to use for a View * @@ -2538,6 +2528,5 @@ export { getModalPaddingStyles, getFontFamilyMonospace, getEmojiPickerStyle, - getKeyboardShortcutModalStyle, getLoginPagePromoStyle, }; From dbfa47ed893a190784165e42b086f40896f1cba8 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Mon, 8 Nov 2021 21:27:10 +0530 Subject: [PATCH 23/38] Changes for code cleanup --- src/components/KeyboardShortcutsModal.js | 2 -- src/libs/KeyboardShortcut/index.js | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 804315c9682b..1cedb0a5d1ef 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -45,7 +45,6 @@ class KeyboardShortcutsModal extends React.PureComponent { } } - /** * Set flag for model visibility * @param {Boolean} flag @@ -74,7 +73,6 @@ class KeyboardShortcutsModal extends React.PureComponent { ); } - render() { const shortcuts = KeyboardShortcut.getKeyboardShortcutMap(); diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index dbc58da7ae13..21b919217c6d 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -3,6 +3,10 @@ import _ from 'underscore'; const events = {}; const keyboardShortcutMap = {}; +/** + * Return the key-value pair for shortcut keys and translate keys + * @returns {Array} + */ function getKeyboardShortcutMap() { const shortcuts = []; _.each(keyboardShortcutMap, (descriptionKey, key) => { @@ -151,7 +155,6 @@ function addKeyToMap(key, modifiers, descriptionKey) { keyboardShortcutMap[shortcutKey] = descriptionKey; } - /** * Subscribes to a keyboard event. * @param {String} key The key to watch, i.e. 'K' or 'Escape' From 666e499b78e863938f7aafe2dd13eb80580397d9 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Mon, 8 Nov 2021 21:42:25 +0530 Subject: [PATCH 24/38] Added check for descriptionKey --- src/libs/KeyboardShortcut/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index 21b919217c6d..01ad81c6df17 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -171,7 +171,9 @@ function subscribe(key, callback, descriptionKey, modifiers = 'shift', captureOn } events[keyCode].push({callback, modifiers: _.isArray(modifiers) ? modifiers : [modifiers], captureOnInputs}); - addKeyToMap(key, modifiers, descriptionKey); + if (descriptionKey) { + addKeyToMap(key, modifiers, descriptionKey); + } return () => unsubscribe(key); } From eeb16d19c8b3e51b2ad0a7176802e22e252a244a Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Mon, 8 Nov 2021 21:46:12 +0530 Subject: [PATCH 25/38] Fixed escape key for dialog --- src/components/KeyboardShortcutsModal.js | 1 - src/components/ScreenWrapper.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 1cedb0a5d1ef..aa3d5b6f5d7a 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -75,7 +75,6 @@ class KeyboardShortcutsModal extends React.PureComponent { render() { const shortcuts = KeyboardShortcut.getKeyboardShortcutMap(); - return ( { this.setState({didScreenTransitionEnd: true}); From fa76933714d1dbf5bb6d7cf7f8411f4171ae7925 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Mon, 8 Nov 2021 23:15:34 +0530 Subject: [PATCH 26/38] Lint fixes --- src/components/KeyboardShortcutsModal.js | 5 +++-- src/libs/KeyboardShortcut/index.js | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index aa3d5b6f5d7a..a504b06e558e 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -40,9 +40,10 @@ class KeyboardShortcutsModal extends React.PureComponent { } componentWillUnmount() { - if (this.unsubscribeShortCutModal) { - this.unsubscribeShortCutModal(); + if (!this.unsubscribeShortCutModal) { + return; } + this.unsubscribeShortCutModal(); } /** diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index 01ad81c6df17..f2147a698f9c 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -134,11 +134,11 @@ function addKeyToMap(key, modifiers, descriptionKey) { let shortcutKey = [key]; if (typeof modifiers === 'string') { shortcutKey.unshift(modifiers); - } else if (Array.isArray(modifiers)) { + } else if (_.isArray(modifiers)) { shortcutKey = [...modifiers, ...shortcutKey]; } - shortcutKey = shortcutKey.map((modifierKey) => { + shortcutKey = _.map(shortcutKey, (modifierKey) => { switch (modifierKey) { case 'control': return 'Ctrl'; From 99e7a4f4977d4fb3559c01efda2c84d251da6fb7 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Mon, 8 Nov 2021 23:46:04 +0530 Subject: [PATCH 27/38] Made modal bottom docked for small screens and changed function name --- src/components/KeyboardShortcutsModal.js | 5 +++-- src/libs/KeyboardShortcut/index.js | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index a504b06e558e..12384add9ea4 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -75,11 +75,12 @@ class KeyboardShortcutsModal extends React.PureComponent { } render() { - const shortcuts = KeyboardShortcut.getKeyboardShortcutMap(); + const shortcuts = KeyboardShortcut.getKeyboardShortcuts(); + const modalType = this.props.isSmallScreenWidth ? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : CONST.MODAL.MODAL_TYPE.CENTERED; return ( this.toggleKeyboardShortcutModal(false)} > diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index f2147a698f9c..1f329b0670d2 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -7,7 +7,7 @@ const keyboardShortcutMap = {}; * Return the key-value pair for shortcut keys and translate keys * @returns {Array} */ -function getKeyboardShortcutMap() { +function getKeyboardShortcuts() { const shortcuts = []; _.each(keyboardShortcutMap, (descriptionKey, key) => { shortcuts.push({key, descriptionKey}); @@ -190,7 +190,7 @@ function subscribe(key, callback, descriptionKey, modifiers = 'shift', captureOn */ const KeyboardShortcut = { subscribe, - getKeyboardShortcutMap, + getKeyboardShortcuts, }; export default KeyboardShortcut; From 1f57f37ac5de184ee01872273c1e8ebd672ec7df Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Tue, 9 Nov 2021 17:32:49 +0530 Subject: [PATCH 28/38] Moved shortcut modifiers (control/meta) logic to utils --- src/components/KeyboardShortcutsModal.js | 7 ++----- src/libs/KeyboardShortcut/index.js | 15 ++++++++++++++- src/libs/Navigation/AppNavigator/AuthScreens.js | 10 ++-------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 12384add9ea4..0595ad1daf4a 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -10,7 +10,7 @@ import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimen import withLocalize, {withLocalizePropTypes} from './withLocalize'; import compose from '../libs/compose'; import KeyboardShortcut from '../libs/KeyboardShortcut'; -import getOperatingSystem from '../libs/getOperatingSystem'; + const propTypes = { /** prop to fetch screen width */ @@ -30,10 +30,7 @@ class KeyboardShortcutsModal extends React.PureComponent { } componentDidMount() { - let shortcutModifiers = ['control']; - if (getOperatingSystem() === CONST.OS.MAC_OS) { - shortcutModifiers = ['meta']; - } + const shortcutModifiers = KeyboardShortcut.getShortcutModifiers(['control']); this.unsubscribeShortCutModal = KeyboardShortcut.subscribe('?', () => { this.toggleKeyboardShortcutModal(true); }, 'openShortcutDialog', shortcutModifiers, true); diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index 1f329b0670d2..441627e2d485 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -1,4 +1,6 @@ import _ from 'underscore'; +import getOperatingSystem from '../getOperatingSystem'; +import CONST from '../../CONST'; const events = {}; const keyboardShortcutMap = {}; @@ -132,7 +134,7 @@ function unsubscribe(key) { */ function addKeyToMap(key, modifiers, descriptionKey) { let shortcutKey = [key]; - if (typeof modifiers === 'string') { + if (_.isString(modifiers)) { shortcutKey.unshift(modifiers); } else if (_.isArray(modifiers)) { shortcutKey = [...modifiers, ...shortcutKey]; @@ -177,6 +179,16 @@ function subscribe(key, callback, descriptionKey, modifiers = 'shift', captureOn return () => unsubscribe(key); } +/** + * Return platform specific modifiers for keys like Control (Cmd) + * @param {Array} modifiers + * @returns {Array} + */ +function getShortcutModifiers(modifiers) { + const isMacOS = getOperatingSystem() === CONST.OS.MAC_OS; + return _.map(modifiers, modifier => (isMacOS && modifier === 'control' ? 'meta' : 'control')); +} + /** * Module storing the different keyboard shortcut * @@ -191,6 +203,7 @@ function subscribe(key, callback, descriptionKey, modifiers = 'shift', captureOn const KeyboardShortcut = { subscribe, getKeyboardShortcuts, + getShortcutModifiers, }; export default KeyboardShortcut; diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 54ae095efe77..f5c92bac469b 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -32,7 +32,6 @@ import NameValuePair from '../../actions/NameValuePair'; import * as Policy from '../../actions/Policy'; import modalCardStyleInterpolator from './modalCardStyleInterpolator'; import createCustomModalStackNavigator from './createCustomModalStackNavigator'; -import getOperatingSystem from '../../getOperatingSystem'; import {fetchFreePlanVerifiedBankAccount, fetchUserWallet} from '../../actions/BankAccounts'; // Main drawer navigator @@ -171,13 +170,8 @@ class AuthScreens extends React.Component { Timing.end(CONST.TIMING.HOMEPAGE_INITIAL_RENDER); - let searchShortcutModifiers = ['control']; - let groupShortcutModifiers = ['control', 'shift']; - - if (getOperatingSystem() === CONST.OS.MAC_OS) { - searchShortcutModifiers = ['meta']; - groupShortcutModifiers = ['meta', 'shift']; - } + const searchShortcutModifiers = KeyboardShortcut.getShortcutModifiers(['control']); + const groupShortcutModifiers = KeyboardShortcut.getShortcutModifiers(['control', 'shift']); // Listen for the key K being pressed so that focus can be given to // the chat switcher, or new group chat From 4c29fc0b7b2d138b9d648b30c558354275a168c7 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 19 Nov 2021 18:18:54 +0530 Subject: [PATCH 29/38] Changed logic for modifiers --- src/CONST.js | 12 +++++++++++- src/libs/KeyboardShortcut/index.js | 12 ++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 9a0fe6e80263..0fe9a40d6559 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -1,5 +1,6 @@ const CLOUDFRONT_URL = 'https://d2k5nsl2zxldvw.cloudfront.net'; const NEW_EXPENSIFY_URL = 'https://new.expensify.com'; +const PLATFORM_OS_MACOS = 'Mac OS'; const CONST = { // 50 megabytes in bytes @@ -119,6 +120,15 @@ const CONST = { IOS: 'ios', ANDROID: 'android', }, + KEYBOARD_SHORTCUT_MODIFIERS: { + CTRL: { + DEFAULT: 'control', + [PLATFORM_OS_MACOS]: 'meta', + }, + SHIFT: { + DEFAULT: 'shift', + }, + }, CURRENCY: { USD: 'USD', }, @@ -360,7 +370,7 @@ const CONST = { OS: { WINDOWS: 'Windows', - MAC_OS: 'Mac OS', + MAC_OS: PLATFORM_OS_MACOS, ANDROID: 'Android', IOS: 'iOS', LINUX: 'Linux', diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index 441627e2d485..ff91bd9ed32e 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -1,4 +1,5 @@ import _ from 'underscore'; +import lodashGet from 'lodash/get'; import getOperatingSystem from '../getOperatingSystem'; import CONST from '../../CONST'; @@ -185,8 +186,15 @@ function subscribe(key, callback, descriptionKey, modifiers = 'shift', captureOn * @returns {Array} */ function getShortcutModifiers(modifiers) { - const isMacOS = getOperatingSystem() === CONST.OS.MAC_OS; - return _.map(modifiers, modifier => (isMacOS && modifier === 'control' ? 'meta' : 'control')); + const operatingSystem = getOperatingSystem(); + return _.map(modifiers, (modifier) => { + if (!_.has(CONST.KEYBOARD_SHORTCUT_MODIFIERS, modifier)) { + return modifier; + } + + const platformModifiers = CONST.KEYBOARD_SHORTCUT_MODIFIERS[modifier]; + return lodashGet(platformModifiers, operatingSystem, platformModifiers.DEFAULT || modifier); + }); } /** From 7de6c54b7de7e58054bf5e529f241404699245bc Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 19 Nov 2021 18:19:19 +0530 Subject: [PATCH 30/38] Fixed typo for KeyboardShortcut --- src/components/KeyboardShortcutsModal.js | 15 +++++++-------- src/languages/en.js | 2 +- src/languages/es.js | 2 +- src/styles/styles.js | 1 - 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 0595ad1daf4a..fa2cc25ef71d 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -20,7 +20,7 @@ const propTypes = { ...withLocalizePropTypes, }; -class KeyboardShortcutsModal extends React.PureComponent { +class KeyboardShortcutsModal extends React.Component { constructor(props) { super(props); @@ -31,20 +31,19 @@ class KeyboardShortcutsModal extends React.PureComponent { componentDidMount() { const shortcutModifiers = KeyboardShortcut.getShortcutModifiers(['control']); - this.unsubscribeShortCutModal = KeyboardShortcut.subscribe('?', () => { + this.unsubscribeShortcutModal = KeyboardShortcut.subscribe('?', () => { this.toggleKeyboardShortcutModal(true); }, 'openShortcutDialog', shortcutModifiers, true); } componentWillUnmount() { - if (!this.unsubscribeShortCutModal) { + if (!this.unsubscribeShortcutModal) { return; } - this.unsubscribeShortCutModal(); + this.unsubscribeShortcutModal(); } /** - * Set flag for model visibility * @param {Boolean} flag */ toggleKeyboardShortcutModal(flag) { @@ -65,7 +64,7 @@ class KeyboardShortcutsModal extends React.PureComponent { {shortcut.key} - {this.props.translate(`keyboardShortCutModal.shortcuts.${shortcut.descriptionKey}`)} + {this.props.translate(`keyboardShortcutModal.shortcuts.${shortcut.descriptionKey}`)} ); @@ -81,9 +80,9 @@ class KeyboardShortcutsModal extends React.PureComponent { containerStyle={styles.keyboardShortcutModalContainer} onClose={() => this.toggleKeyboardShortcutModal(false)} > - this.toggleKeyboardShortcutModal(false)} /> + this.toggleKeyboardShortcutModal(false)} /> - {this.props.translate('keyboardShortCutModal.subtitle')} + {this.props.translate('keyboardShortcutModal.subtitle')} {_.map(shortcuts, (shortcut, index) => { diff --git a/src/languages/en.js b/src/languages/en.js index 6d894fed97dc..6217299605b9 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -774,7 +774,7 @@ export default { emojiPicker: { skinTonePickerLabel: 'Change default skin tone', }, - keyboardShortCutModal: { + keyboardShortcutModal: { title: 'Keyboard Shortcuts', subtitle: 'Save time with these handy keyboard shortcuts:', shortcuts: { diff --git a/src/languages/es.js b/src/languages/es.js index 9bbb20652833..b1bcf02efbaa 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -776,7 +776,7 @@ export default { emojiPicker: { skinTonePickerLabel: 'Elige el tono de piel por defecto', }, - keyboardShortCutModal: { + keyboardShortcutModal: { title: 'Atajos de teclado', subtitle: 'Ahorra tiempo con estos atajos de teclado:', shortcuts: { diff --git a/src/styles/styles.js b/src/styles/styles.js index d923d100f2aa..1536b6340e5d 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2129,7 +2129,6 @@ const styles = { googleListView: { transform: [{scale: 0}], - }, }; From e5b034d100cee87aceeae865d2d81dda3d79e3c5 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 19 Nov 2021 18:47:28 +0530 Subject: [PATCH 31/38] Split toggle func to hide and show --- src/components/KeyboardShortcutsModal.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index fa2cc25ef71d..94cd508d672a 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -27,12 +27,15 @@ class KeyboardShortcutsModal extends React.Component { this.state = { isOpen: false, }; + + this.showKeyboardShortcutModal = this.showKeyboardShortcutModal.bind(this); + this.hideKeyboardShortcutModal = this.hideKeyboardShortcutModal.bind(this); } componentDidMount() { - const shortcutModifiers = KeyboardShortcut.getShortcutModifiers(['control']); + const shortcutModifiers = KeyboardShortcut.getShortcutModifiers(['CTRL']); this.unsubscribeShortcutModal = KeyboardShortcut.subscribe('?', () => { - this.toggleKeyboardShortcutModal(true); + this.showKeyboardShortcutModal(); }, 'openShortcutDialog', shortcutModifiers, true); } @@ -43,11 +46,12 @@ class KeyboardShortcutsModal extends React.Component { this.unsubscribeShortcutModal(); } - /** - * @param {Boolean} flag - */ - toggleKeyboardShortcutModal(flag) { - this.setState({isOpen: flag}); + showKeyboardShortcutModal() { + this.setState({isOpen: true}); + } + + hideKeyboardShortcutModal() { + this.setState({isOpen: false}); } renderRow(shortcut, isFirstRow) { @@ -78,9 +82,9 @@ class KeyboardShortcutsModal extends React.Component { isVisible={this.state.isOpen} type={modalType} containerStyle={styles.keyboardShortcutModalContainer} - onClose={() => this.toggleKeyboardShortcutModal(false)} + onClose={() => this.hideKeyboardShortcutModal()} > - this.toggleKeyboardShortcutModal(false)} /> + this.hideKeyboardShortcutModal()} /> {this.props.translate('keyboardShortcutModal.subtitle')} From 3cbd1bfc8c49ae47ecbb097af1a7567c9dd62a7b Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 19 Nov 2021 18:48:26 +0530 Subject: [PATCH 32/38] Removed hardcoding of the shortcuts to CONST --- src/CONST.js | 5 +++++ src/libs/KeyboardShortcut/index.js | 13 +------------ src/libs/Navigation/AppNavigator/AuthScreens.js | 4 ++-- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 0fe9a40d6559..4862bb6ba611 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -129,6 +129,11 @@ const CONST = { DEFAULT: 'shift', }, }, + KEYBOARD_SHORTCUT_KEY_DISPLAY_NAME: { + CONTROL: 'Ctrl', + META: 'Cmd', + SHIFT: 'Shift', + }, CURRENCY: { USD: 'USD', }, diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index ff91bd9ed32e..d2d03ecfbd05 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -141,18 +141,7 @@ function addKeyToMap(key, modifiers, descriptionKey) { shortcutKey = [...modifiers, ...shortcutKey]; } - shortcutKey = _.map(shortcutKey, (modifierKey) => { - switch (modifierKey) { - case 'control': - return 'Ctrl'; - case 'meta': - return 'Cmd'; - case 'shift': - return 'Shift'; - default: - return modifierKey; - } - }); + shortcutKey = _.map(shortcutKey, modifier => lodashGet(CONST.KEYBOARD_SHORTCUT_KEY_DISPLAY_NAME, modifier.toUpperCase(), modifier)); shortcutKey = shortcutKey.join(' + '); keyboardShortcutMap[shortcutKey] = descriptionKey; diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index f5c92bac469b..e9e70c2491e5 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -170,8 +170,8 @@ class AuthScreens extends React.Component { Timing.end(CONST.TIMING.HOMEPAGE_INITIAL_RENDER); - const searchShortcutModifiers = KeyboardShortcut.getShortcutModifiers(['control']); - const groupShortcutModifiers = KeyboardShortcut.getShortcutModifiers(['control', 'shift']); + const searchShortcutModifiers = KeyboardShortcut.getShortcutModifiers(['CTRL']); + const groupShortcutModifiers = KeyboardShortcut.getShortcutModifiers(['CTRL', 'SHIFT']); // Listen for the key K being pressed so that focus can be given to // the chat switcher, or new group chat From fc03898322bd6058404dfc345b4b36f3de094f02 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 19 Nov 2021 19:01:13 +0530 Subject: [PATCH 33/38] Pick all shortcut configs from CONST --- src/CONST.js | 22 +++++++++++++++++++ src/components/KeyboardShortcutsModal.js | 7 +++--- src/components/ScreenWrapper.js | 6 +++-- .../Navigation/AppNavigator/AuthScreens.js | 15 ++++++++----- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 4862bb6ba611..00fb493b8907 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -129,6 +129,28 @@ const CONST = { DEFAULT: 'shift', }, }, + KEYBOARD_SHORTCUTS: { + SEARCH: { + descriptionKey: 'search', + shortcutKey: 'K', + modifiers: ['CTRL'], + }, + NEW_GROUP: { + descriptionKey: 'newGroup', + shortcutKey: 'K', + modifiers: ['CTRL', 'SHIFT'], + }, + SHORTCUT_MODAL: { + descriptionKey: 'openShortcutDialog', + shortcutKey: '?', + modifiers: ['CTRL', 'SHIFT'], + }, + ESCAPE: { + descriptionKey: 'escape', + shortcutKey: 'Escape', + modifiers: [], + }, + }, KEYBOARD_SHORTCUT_KEY_DISPLAY_NAME: { CONTROL: 'Ctrl', META: 'Cmd', diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 94cd508d672a..9d006bcc9698 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -33,10 +33,11 @@ class KeyboardShortcutsModal extends React.Component { } componentDidMount() { - const shortcutModifiers = KeyboardShortcut.getShortcutModifiers(['CTRL']); - this.unsubscribeShortcutModal = KeyboardShortcut.subscribe('?', () => { + const shortcutConfig = CONST.KEYBOARD_SHORTCUTS.SHORTCUT_MODAL; + const shortcutModifiers = KeyboardShortcut.getShortcutModifiers(shortcutConfig.modifiers); + this.unsubscribeShortcutModal = KeyboardShortcut.subscribe(shortcutConfig.shortcutKey, () => { this.showKeyboardShortcutModal(); - }, 'openShortcutDialog', shortcutModifiers, true); + }, shortcutConfig.descriptionKey, shortcutModifiers, true); } componentWillUnmount() { diff --git a/src/components/ScreenWrapper.js b/src/components/ScreenWrapper.js index 82cea12c3f97..34185c95d8ed 100644 --- a/src/components/ScreenWrapper.js +++ b/src/components/ScreenWrapper.js @@ -13,6 +13,7 @@ import onScreenTransitionEnd from '../libs/onScreenTransitionEnd'; import Navigation from '../libs/Navigation/Navigation'; import compose from '../libs/compose'; import ONYXKEYS from '../ONYXKEYS'; +import CONST from '../CONST'; const propTypes = { /** Array of additional styles to add */ @@ -68,13 +69,14 @@ class ScreenWrapper extends React.Component { } componentDidMount() { - this.unsubscribeEscapeKey = KeyboardShortcut.subscribe('Escape', () => { + const shortcutConfig = CONST.KEYBOARD_SHORTCUTS.ESCAPE; + this.unsubscribeEscapeKey = KeyboardShortcut.subscribe(shortcutConfig.shortcutKey, () => { if (this.props.modal.willAlertModalBecomeVisible) { return; } Navigation.dismissModal(); - }, 'escape', [], true); + }, shortcutConfig.descriptionKey, shortcutConfig.modifiers, true); this.unsubscribeTransitionEnd = onScreenTransitionEnd(this.props.navigation, () => { this.setState({didScreenTransitionEnd: true}); diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index e9e70c2491e5..b9ebe89fb9f9 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -170,18 +170,21 @@ class AuthScreens extends React.Component { Timing.end(CONST.TIMING.HOMEPAGE_INITIAL_RENDER); - const searchShortcutModifiers = KeyboardShortcut.getShortcutModifiers(['CTRL']); - const groupShortcutModifiers = KeyboardShortcut.getShortcutModifiers(['CTRL', 'SHIFT']); + const searchShortcutConfig = CONST.KEYBOARD_SHORTCUTS.SEARCH; + const searchShortcutModifiers = KeyboardShortcut.getShortcutModifiers(searchShortcutConfig.modifiers); + + const groupShortcutConfig = CONST.KEYBOARD_SHORTCUTS.NEW_GROUP; + const groupShortcutModifiers = KeyboardShortcut.getShortcutModifiers(groupShortcutConfig.modifiers); // Listen for the key K being pressed so that focus can be given to // the chat switcher, or new group chat // based on the key modifiers pressed and the operating system - this.unsubscribeSearchShortcut = KeyboardShortcut.subscribe('K', () => { + this.unsubscribeSearchShortcut = KeyboardShortcut.subscribe(searchShortcutConfig.shortcutKey, () => { Navigation.navigate(ROUTES.SEARCH); - }, 'search', searchShortcutModifiers, true); - this.unsubscribeGroupShortcut = KeyboardShortcut.subscribe('K', () => { + }, groupShortcutConfig.descriptionKey, searchShortcutModifiers, true); + this.unsubscribeGroupShortcut = KeyboardShortcut.subscribe(groupShortcutConfig.shortcutKey, () => { Navigation.navigate(ROUTES.NEW_GROUP); - }, 'newGroup', groupShortcutModifiers, true); + }, groupShortcutConfig.descriptionKey, groupShortcutModifiers, true); } shouldComponentUpdate(nextProps) { From eb6ef1c56f3b8a3a18ad85bf03e4cba231423614 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 19 Nov 2021 19:15:57 +0530 Subject: [PATCH 34/38] Added enter configuration for keyboard shortcuts --- src/CONST.js | 5 +++++ src/components/Button.js | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 00fb493b8907..688c4e595c49 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -150,6 +150,11 @@ const CONST = { shortcutKey: 'Escape', modifiers: [], }, + ENTER: { + descriptionKey: null, + shortcutKey: 'Enter', + modifiers: [], + }, }, KEYBOARD_SHORTCUT_KEY_DISPLAY_NAME: { CONTROL: 'Ctrl', diff --git a/src/components/Button.js b/src/components/Button.js index 0ecfef5b1272..ed55575d46e2 100644 --- a/src/components/Button.js +++ b/src/components/Button.js @@ -8,6 +8,7 @@ import OpacityView from './OpacityView'; import Text from './Text'; import KeyboardShortcut from '../libs/KeyboardShortcut'; import Icon from './Icon'; +import CONST from '../CONST'; const propTypes = { /** The text for the button label */ @@ -90,13 +91,15 @@ class Button extends Component { return; } + const shortcutConfig = CONST.KEYBOARD_SHORTCUTS.ENTER; + // Setup and attach keypress handler for pressing the button with Enter key - this.unsubscribe = KeyboardShortcut.subscribe('Enter', () => { + this.unsubscribe = KeyboardShortcut.subscribe(shortcutConfig.shortcutKey, () => { if (this.props.isDisabled || this.props.isLoading) { return; } this.props.onPress(); - }, null, [], true); + }, shortcutConfig.descriptionKey, shortcutConfig.modifiers7, true); } componentWillUnmount() { From e2e456c64b6f14c9fe2d4d81b1ac1872e26485d4 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Fri, 19 Nov 2021 19:21:51 +0530 Subject: [PATCH 35/38] Fixed typo for Button --- src/components/Button.js | 2 +- src/components/KeyboardShortcutsModal.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Button.js b/src/components/Button.js index ed55575d46e2..8e346c96358e 100644 --- a/src/components/Button.js +++ b/src/components/Button.js @@ -99,7 +99,7 @@ class Button extends Component { return; } this.props.onPress(); - }, shortcutConfig.descriptionKey, shortcutConfig.modifiers7, true); + }, shortcutConfig.descriptionKey, shortcutConfig.modifiers, true); } componentWillUnmount() { diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 9d006bcc9698..0e1b97a15704 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -11,7 +11,6 @@ import withLocalize, {withLocalizePropTypes} from './withLocalize'; import compose from '../libs/compose'; import KeyboardShortcut from '../libs/KeyboardShortcut'; - const propTypes = { /** prop to fetch screen width */ ...windowDimensionsPropTypes, From f09b02781919aef406e810f4467cb46036d9340f Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Wed, 24 Nov 2021 02:25:14 +0530 Subject: [PATCH 36/38] Added jsdocs and changed function calls --- src/components/KeyboardShortcutsModal.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 0e1b97a15704..fcef9ea4a835 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -54,6 +54,12 @@ class KeyboardShortcutsModal extends React.Component { this.setState({isOpen: false}); } + /** + * Render single row for the Keyboard shortcuts with description + * @param {Object} shortcut + * @param {Boolean} isFirstRow + * @returns {*} + */ renderRow(shortcut, isFirstRow) { return ( this.hideKeyboardShortcutModal()} + onClose={this.hideKeyboardShortcutModal} > - this.hideKeyboardShortcutModal()} /> + {this.props.translate('keyboardShortcutModal.subtitle')} From 2eeed6997d0c703f17c0f782925283ae632c14a0 Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Wed, 24 Nov 2021 02:25:47 +0530 Subject: [PATCH 37/38] Unified representation of shortcut object --- src/components/KeyboardShortcutsModal.js | 4 ++-- src/libs/KeyboardShortcut/index.js | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index fcef9ea4a835..a13b94d16446 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -68,10 +68,10 @@ class KeyboardShortcutsModal extends React.Component { styles.flex1, isFirstRow && styles.keyboardShortcutTableFirstRow, ]} - key={shortcut.key} + key={shortcut.displayName} > - {shortcut.key} + {shortcut.displayName} {this.props.translate(`keyboardShortcutModal.shortcuts.${shortcut.descriptionKey}`)} diff --git a/src/libs/KeyboardShortcut/index.js b/src/libs/KeyboardShortcut/index.js index d2d03ecfbd05..b400aca82d60 100644 --- a/src/libs/KeyboardShortcut/index.js +++ b/src/libs/KeyboardShortcut/index.js @@ -11,12 +11,7 @@ const keyboardShortcutMap = {}; * @returns {Array} */ function getKeyboardShortcuts() { - const shortcuts = []; - _.each(keyboardShortcutMap, (descriptionKey, key) => { - shortcuts.push({key, descriptionKey}); - }); - - return shortcuts; + return _.values(keyboardShortcutMap); } /** @@ -134,17 +129,22 @@ function unsubscribe(key) { * @param {String} descriptionKey Translation key for shortcut description */ function addKeyToMap(key, modifiers, descriptionKey) { - let shortcutKey = [key]; + let displayName = [key]; if (_.isString(modifiers)) { - shortcutKey.unshift(modifiers); + displayName.unshift(modifiers); } else if (_.isArray(modifiers)) { - shortcutKey = [...modifiers, ...shortcutKey]; + displayName = [...modifiers, ...displayName]; } - shortcutKey = _.map(shortcutKey, modifier => lodashGet(CONST.KEYBOARD_SHORTCUT_KEY_DISPLAY_NAME, modifier.toUpperCase(), modifier)); + displayName = _.map(displayName, modifier => lodashGet(CONST.KEYBOARD_SHORTCUT_KEY_DISPLAY_NAME, modifier.toUpperCase(), modifier)); - shortcutKey = shortcutKey.join(' + '); - keyboardShortcutMap[shortcutKey] = descriptionKey; + displayName = displayName.join(' + '); + keyboardShortcutMap[displayName] = { + shortcutKey: key, + descriptionKey, + displayName, + modifiers, + }; } /** From 06c77ce828f5a8cb78e5db47d065ee910f5c3dbf Mon Sep 17 00:00:00 2001 From: Akshaya Salvi Date: Wed, 24 Nov 2021 02:25:57 +0530 Subject: [PATCH 38/38] Fixed typos in shortcuts --- src/CONST.js | 2 +- src/libs/Navigation/AppNavigator/AuthScreens.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 688c4e595c49..af7dbc180de9 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -143,7 +143,7 @@ const CONST = { SHORTCUT_MODAL: { descriptionKey: 'openShortcutDialog', shortcutKey: '?', - modifiers: ['CTRL', 'SHIFT'], + modifiers: ['CTRL'], }, ESCAPE: { descriptionKey: 'escape', diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index b9ebe89fb9f9..a6c0131eafbf 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -181,7 +181,7 @@ class AuthScreens extends React.Component { // based on the key modifiers pressed and the operating system this.unsubscribeSearchShortcut = KeyboardShortcut.subscribe(searchShortcutConfig.shortcutKey, () => { Navigation.navigate(ROUTES.SEARCH); - }, groupShortcutConfig.descriptionKey, searchShortcutModifiers, true); + }, searchShortcutConfig.descriptionKey, searchShortcutModifiers, true); this.unsubscribeGroupShortcut = KeyboardShortcut.subscribe(groupShortcutConfig.shortcutKey, () => { Navigation.navigate(ROUTES.NEW_GROUP); }, groupShortcutConfig.descriptionKey, groupShortcutModifiers, true);