diff --git a/src/libs/virtualKeyboard/index.js b/src/libs/virtualKeyboard/index.js new file mode 100644 index 000000000000..f28dc84c0bcf --- /dev/null +++ b/src/libs/virtualKeyboard/index.js @@ -0,0 +1,18 @@ +import _ from 'underscore'; + +/** + * Is the virtual keyboard open? + * + * @returns {Boolean|null} – null if the VirtualKeyboard API is unavailable + */ +function isOpen() { + if (!_.has(navigator, 'virtualKeyboard')) { + return null; + } + return navigator.virtualKeyboard.boundingRect.y > 0; +} + +export { + // eslint-disable-next-line import/prefer-default-export + isOpen, +}; diff --git a/src/libs/virtualKeyboard/index.native.js b/src/libs/virtualKeyboard/index.native.js new file mode 100644 index 000000000000..6c21a32ffcdf --- /dev/null +++ b/src/libs/virtualKeyboard/index.native.js @@ -0,0 +1,33 @@ +import {Keyboard} from 'react-native'; + +let isVirtualKeyboardOpen = false; + +Keyboard.addListener( + 'keyboardDidShow', + () => { + isVirtualKeyboardOpen = true; + }, +); + +Keyboard.addListener( + 'keyboardDidHide', + () => { + isVirtualKeyboardOpen = false; + }, +); + +/** + * Is the virtual keyboard open? + * + * Note – the web equivalent of this function may return null. + * + * @returns {Boolean} + */ +function isOpen() { + return isVirtualKeyboardOpen; +} + +export { + // eslint-disable-next-line import/prefer-default-export + isOpen, +}; diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 51759e6bb846..cb85d3267078 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -49,6 +49,8 @@ import {withNetwork, withPersonalDetails} from '../../../components/OnyxProvider import DateUtils from '../../../libs/DateUtils'; import Tooltip from '../../../components/Tooltip'; import * as EmojiUtils from '../../../libs/EmojiUtils'; +import canUseTouchScreen from '../../../libs/canUseTouchscreen'; +import * as VirtualKeyboard from '../../../libs/virtualKeyboard'; const propTypes = { /** Beta features list */ @@ -353,13 +355,25 @@ class ReportActionCompose extends React.Component { } } + /** + * As of January 2022, the VirtualKeyboard web API is not available in all browsers yet + * If it is unavailable, we default to assuming that the virtual keyboard is open on touch-enabled devices. + * See https://github.com/Expensify/App/issues/6767 for additional context. + * + * @returns {Boolean} + */ + shouldAssumeVirtualKeyboardIsOpen() { + const isOpen = VirtualKeyboard.isOpen(); + return _.isNull(isOpen) ? canUseTouchScreen() : isOpen; + } + /** * Listens for keyboard shortcuts and applies the action * * @param {Object} e */ triggerHotkeyActions(e) { - if (!e) { + if (!e || this.shouldAssumeVirtualKeyboardIsOpen()) { return; }