diff --git a/src/components/ArrowKeyFocusManager.js b/src/components/ArrowKeyFocusManager.js index 72a590547fa0..e548067f17aa 100644 --- a/src/components/ArrowKeyFocusManager.js +++ b/src/components/ArrowKeyFocusManager.js @@ -52,7 +52,7 @@ class ArrowKeyFocusManager extends Component { } this.props.onFocusedIndexChanged(newFocusedIndex); - }, arrowUpConfig.descriptionKey, arrowUpConfig.modifiers, true, false, 0, true, [this.props.shouldExcludeTextAreaNodes && 'TEXTAREA']); + }, arrowUpConfig.descriptionKey, arrowUpConfig.modifiers, true, false, 1, true, [this.props.shouldExcludeTextAreaNodes && 'TEXTAREA']); this.unsubscribeArrowDownKey = KeyboardShortcut.subscribe(arrowDownConfig.shortcutKey, () => { if (this.props.maxIndex < 0) { @@ -70,7 +70,7 @@ class ArrowKeyFocusManager extends Component { } this.props.onFocusedIndexChanged(newFocusedIndex); - }, arrowDownConfig.descriptionKey, arrowDownConfig.modifiers, true, false, 0, true, [this.props.shouldExcludeTextAreaNodes && 'TEXTAREA']); + }, arrowDownConfig.descriptionKey, arrowDownConfig.modifiers, true, false, 1, true, [this.props.shouldExcludeTextAreaNodes && 'TEXTAREA']); } componentWillUnmount() { diff --git a/src/components/ButtonWithMenu.js b/src/components/ButtonWithMenu.js index eea6b5ffb835..1f8d9a7c0ec5 100644 --- a/src/components/ButtonWithMenu.js +++ b/src/components/ButtonWithMenu.js @@ -75,6 +75,7 @@ class ButtonWithMenu extends PureComponent { text={selectedItem.text} onPress={event => this.props.onPress(event, this.props.options[0].value)} pressOnEnter + enterKeyEventListenerPriority={1} /> )} {this.props.options.length > 1 && ( diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index a5454e280f0d..7dd2adf72585 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -40,19 +40,46 @@ class KeyboardShortcutsModal extends React.Component { KeyboardShortcutsActions.showKeyboardShortcutModal(); }, openShortcutModalConfig.descriptionKey, openShortcutModalConfig.modifiers, true); - const closeShortcutModalConfig = CONST.KEYBOARD_SHORTCUTS.ESCAPE; - this.unsubscribeEscapeModal = KeyboardShortcut.subscribe(closeShortcutModalConfig.shortcutKey, () => { + // Allow closing the modal with the both Enter and Escape keys + // Both callbacks have the lowest priority (0) to ensure that they are called before any other callbacks + // and configured so that event propagation is stopped after the callback is called (only when the modal is open) + const closeShortcutEscapeModalConfig = CONST.KEYBOARD_SHORTCUTS.ESCAPE; + this.unsubscribeCloseEscapeModal = KeyboardShortcut.subscribe(closeShortcutEscapeModalConfig.shortcutKey, () => { ModalActions.close(); KeyboardShortcutsActions.hideKeyboardShortcutModal(); - }, closeShortcutModalConfig.descriptionKey, closeShortcutModalConfig.modifiers, true, true); + }, closeShortcutEscapeModalConfig.descriptionKey, closeShortcutEscapeModalConfig.modifiers, true, true); + + const closeShortcutEnterModalConfig = CONST.KEYBOARD_SHORTCUTS.ENTER; + this.unsubscribeCloseEnterModal = KeyboardShortcut.subscribe(closeShortcutEnterModalConfig.shortcutKey, () => { + ModalActions.close(); + KeyboardShortcutsActions.hideKeyboardShortcutModal(); + }, closeShortcutEnterModalConfig.descriptionKey, closeShortcutEnterModalConfig.modifiers, true, () => !this.props.isShortcutsModalOpen); + + // Intercept arrow up and down keys to prevent scrolling ArrowKeyFocusManager while this modal is open + const arrowUpConfig = CONST.KEYBOARD_SHORTCUTS.ARROW_UP; + this.unsubscribeArrowUpKey = KeyboardShortcut.subscribe(arrowUpConfig.shortcutKey, () => { + }, arrowUpConfig.descriptionKey, arrowUpConfig.modifiers, true, () => !this.props.isShortcutsModalOpen); + + const arrowDownConfig = CONST.KEYBOARD_SHORTCUTS.ARROW_DOWN; + this.unsubscribeArrowDownKey = KeyboardShortcut.subscribe(arrowDownConfig.shortcutKey, () => { + }, arrowDownConfig.descriptionKey, arrowDownConfig.modifiers, true, () => !this.props.isShortcutsModalOpen); } componentWillUnmount() { if (this.unsubscribeShortcutModal) { this.unsubscribeShortcutModal(); } - if (this.unsubscribeEscapeModal) { - this.unsubscribeEscapeModal(); + if (this.unsubscribeCloseEscapeModal) { + this.unsubscribeCloseEscapeModal(); + } + if (this.unsubscribeCloseEnterModal) { + this.unsubscribeCloseEnterModal(); + } + if (this.unsubscribeArrowUpKey) { + this.unsubscribeArrowUpKey(); + } + if (this.unsubscribeArrowDownKey) { + this.unsubscribeArrowDownKey(); } } diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 027899e9be9b..4f8c1425eaf8 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -70,6 +70,7 @@ class BaseOptionsSelector extends Component { enterConfig.modifiers, true, () => !this.state.allOptions[this.state.focusedIndex], + 1, ); const CTRLEnterConfig = CONST.KEYBOARD_SHORTCUTS.CTRL_ENTER; @@ -359,7 +360,7 @@ class BaseOptionsSelector extends Component { text={defaultConfirmButtonText} onPress={this.props.onConfirmSelection} pressOnEnter - enterKeyEventListenerPriority={1} + enterKeyEventListenerPriority={2} /> )} {this.props.footerContent} diff --git a/src/pages/iou/steps/MoneyRequestAmountPage.js b/src/pages/iou/steps/MoneyRequestAmountPage.js index 7fb169fa3d84..fd788003823b 100755 --- a/src/pages/iou/steps/MoneyRequestAmountPage.js +++ b/src/pages/iou/steps/MoneyRequestAmountPage.js @@ -354,6 +354,7 @@ class MoneyRequestAmountPage extends React.Component { pressOnEnter isDisabled={!this.state.amount.length || parseFloat(this.state.amount) < 0.01} text={this.props.buttonText} + enterKeyEventListenerPriority={1} />