-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Standardize keyboard libs for determining when the keyboard is open #13629
Changes from all commits
e9e43b2
a108ab0
11f1f55
5f471d5
8889d05
7f7f359
6c81c55
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,79 @@ | ||
import React, {Component} from 'react'; | ||
/* eslint-disable react/no-unused-state */ | ||
import React, {forwardRef, createContext} from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import {Keyboard} from 'react-native'; | ||
import getComponentDisplayName from '../libs/getComponentDisplayName'; | ||
|
||
const withKeyboardStatePropTypes = { | ||
/** Returns whether keyboard is open */ | ||
isShown: PropTypes.bool.isRequired, | ||
const KeyboardStateContext = createContext(null); | ||
const keyboardStatePropTypes = { | ||
/** Whether or not the keyboard is open */ | ||
isKeyboardShown: PropTypes.bool.isRequired, | ||
}; | ||
|
||
export default function withKeyboardState(WrappedComponent) { | ||
const WithKeyboardState = class extends Component { | ||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
isShown: false, | ||
}; | ||
} | ||
const keyboardStateProviderPropTypes = { | ||
/* Actual content wrapped by this component */ | ||
children: PropTypes.node.isRequired, | ||
}; | ||
|
||
class KeyboardStateProvider extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
isKeyboardShown: false, | ||
}; | ||
} | ||
|
||
componentDidMount() { | ||
this.keyboardDidShowListener = Keyboard.addListener( | ||
'keyboardDidShow', | ||
() => { | ||
this.setState({isShown: true}); | ||
}, | ||
); | ||
this.keyboardDidHideListener = Keyboard.addListener( | ||
'keyboardDidHide', | ||
() => { | ||
this.setState({isShown: false}); | ||
}, | ||
); | ||
} | ||
componentDidMount() { | ||
this.keyboardDidShowListener = Keyboard.addListener( | ||
'keyboardDidShow', | ||
() => { | ||
this.setState({isKeyboardShown: true}); | ||
}, | ||
); | ||
this.keyboardDidHideListener = Keyboard.addListener( | ||
'keyboardDidHide', | ||
() => { | ||
this.setState({isKeyboardShown: false}); | ||
}, | ||
); | ||
} | ||
|
||
componentWillUnmount() { | ||
this.keyboardDidShowListener.remove(); | ||
this.keyboardDidHideListener.remove(); | ||
} | ||
componentWillUnmount() { | ||
this.keyboardDidShowListener.remove(); | ||
this.keyboardDidHideListener.remove(); | ||
} | ||
|
||
render() { | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
return <WrappedComponent {...this.props} isShown={this.state.isShown} />; | ||
} | ||
}; | ||
render() { | ||
return ( | ||
<KeyboardStateContext.Provider value={this.state}> | ||
{this.props.children} | ||
</KeyboardStateContext.Provider> | ||
); | ||
} | ||
} | ||
|
||
KeyboardStateProvider.propTypes = keyboardStateProviderPropTypes; | ||
|
||
WithKeyboardState.displayName = `WithKeyboardState(${getComponentDisplayName(WrappedComponent)})`; | ||
WithKeyboardState.propTypes = { | ||
forwardedRef: PropTypes.oneOfType([ | ||
PropTypes.func, | ||
PropTypes.shape({current: PropTypes.instanceOf(React.Component)}), | ||
]), | ||
}; | ||
WithKeyboardState.defaultProps = { | ||
forwardedRef: undefined, | ||
}; | ||
return React.forwardRef((props, ref) => ( | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
<WithKeyboardState {...props} forwardedRef={ref} /> | ||
/** | ||
* @param {React.Component} WrappedComponent | ||
* @returns {React.Component} | ||
*/ | ||
export default function withKeyboardState(WrappedComponent) { | ||
const WithKeyboardState = forwardRef((props, ref) => ( | ||
<KeyboardStateContext.Consumer> | ||
{keyboardStateProps => ( | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
<WrappedComponent {...keyboardStateProps} {...props} ref={ref} /> | ||
)} | ||
</KeyboardStateContext.Consumer> | ||
)); | ||
|
||
WithKeyboardState.displayName = `withKeyboardState(${getComponentDisplayName(WrappedComponent)})`; | ||
return WithKeyboardState; | ||
} | ||
|
||
export { | ||
withKeyboardStatePropTypes, | ||
KeyboardStateProvider, | ||
keyboardStatePropTypes, | ||
}; |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,11 +21,8 @@ import ReportTypingIndicator from './ReportTypingIndicator'; | |
import AttachmentModal from '../../../components/AttachmentModal'; | ||
import compose from '../../../libs/compose'; | ||
import PopoverMenu from '../../../components/PopoverMenu'; | ||
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; | ||
import withDrawerState from '../../../components/withDrawerState'; | ||
import CONST from '../../../CONST'; | ||
import canFocusInputOnScreenFocus from '../../../libs/canFocusInputOnScreenFocus'; | ||
import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; | ||
import Permissions from '../../../libs/Permissions'; | ||
import Navigation from '../../../libs/Navigation/Navigation'; | ||
import ROUTES from '../../../ROUTES'; | ||
|
@@ -39,7 +36,6 @@ import {withNetwork, withPersonalDetails} from '../../../components/OnyxProvider | |
import * as User from '../../../libs/actions/User'; | ||
import Tooltip from '../../../components/Tooltip'; | ||
import EmojiPickerButton from '../../../components/EmojiPicker/EmojiPickerButton'; | ||
import VirtualKeyboard from '../../../libs/VirtualKeyboard'; | ||
import canUseTouchScreen from '../../../libs/canUseTouchscreen'; | ||
import toggleReportActionComposeView from '../../../libs/toggleReportActionComposeView'; | ||
import OfflineIndicator from '../../../components/OfflineIndicator'; | ||
|
@@ -49,6 +45,10 @@ import * as EmojiUtils from '../../../libs/EmojiUtils'; | |
import reportPropTypes from '../../reportPropTypes'; | ||
import ReportDropUI from './ReportDropUI'; | ||
import DragAndDrop from '../../../components/DragAndDrop'; | ||
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; | ||
import withDrawerState from '../../../components/withDrawerState'; | ||
import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; | ||
import withKeyboardState, {keyboardStatePropTypes} from '../../../components/withKeyboardState'; | ||
|
||
const propTypes = { | ||
/** Beta features list */ | ||
|
@@ -99,6 +99,7 @@ const propTypes = { | |
...windowDimensionsPropTypes, | ||
...withLocalizePropTypes, | ||
...withCurrentUserPersonalDetailsPropTypes, | ||
...keyboardStatePropTypes, | ||
}; | ||
|
||
const defaultProps = { | ||
|
@@ -430,7 +431,8 @@ class ReportActionCompose extends React.Component { | |
* @param {Object} e | ||
*/ | ||
triggerHotkeyActions(e) { | ||
if (!e || VirtualKeyboard.shouldAssumeIsOpen()) { | ||
// Do not trigger actions for mobileWeb or native clients that have the keyboard open because for those devices, we want the return key to insert newlines rather than submit the form | ||
if (!e || this.props.isSmallScreenWidth || this.props.isKeyboardShown) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did we test it against resized the Desktop app? I think we do not want that to behave like mobile app as that does not have Virtual Keyboard. cc: @thesahindia There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is expected (#13629 (comment), slack thread) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for sharing. Hmm, I can't give my full approval here without testing but let's hope there are no regressions from this. Anyways, you approved so this should be OK. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi, just dropping a tiny tiny note that when a desktop window is resized to mobile, the Enter key behaviour changes and isn't consistent with full sized window. Causing bug - #17206 |
||
return; | ||
} | ||
|
||
|
@@ -741,6 +743,7 @@ export default compose( | |
withNetwork(), | ||
withPersonalDetails(), | ||
withCurrentUserPersonalDetails, | ||
withKeyboardState, | ||
withOnyx({ | ||
betas: { | ||
key: ONYXKEYS.BETAS, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, we caused a console error with this change. #13862
Why?
keyboardStatePropTypes
contains native only props but being used for all platforms.