Skip to content

Commit

Permalink
Merge pull request #21124 from adamgrzybowski/@swm/navigation-refacto…
Browse files Browse the repository at this point in the history
…r-disable-keyboard-avoiding-view

[navigation-refactor ] Disable KeyboardAvoidingView for the BaseSidebarScreen and fix KeyboardAvoidingView used with react-freeze
  • Loading branch information
amyevans authored Jun 27, 2023
2 parents 27d657e + 6395e38 commit e029bb1
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 1 deletion.
87 changes: 87 additions & 0 deletions patches/react-native+0.71.2-alpha.3.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
diff --git a/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js b/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js
index 2f48f9e..6418c76 100644
--- a/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js
+++ b/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js
@@ -65,6 +65,7 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
_subscriptions: Array<EventSubscription> = [];
viewRef: {current: React.ElementRef<typeof View> | null, ...};
_initialFrameHeight: number = 0;
+ _bottom: number = 0;

constructor(props: Props) {
super(props);
@@ -107,18 +108,20 @@ class KeyboardAvoidingView extends React.Component<Props, State> {

_onKeyboardChange = (event: ?KeyboardEvent) => {
this._keyboardEvent = event;
+ // $FlowFixMe[unused-promise]
this._updateBottomIfNecessary();
};

_onLayout = async (event: ViewLayoutEvent) => {
- const wasFrameNull = this._frame == null;
+ const oldFrame = this._frame;
this._frame = event.nativeEvent.layout;
if (!this._initialFrameHeight) {
// save the initial frame height, before the keyboard is visible
this._initialFrameHeight = this._frame.height;
}

- if (wasFrameNull) {
+ // update bottom height for the first time or when the height is changed
+ if (!oldFrame || oldFrame.height !== this._frame.height) {
await this._updateBottomIfNecessary();
}

@@ -127,20 +130,31 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
}
};

+ // Avoid unnecessary renders if the KeyboardAvoidingView is disabled.
+ _setBottom = (value: number) => {
+ const {enabled = true} = this.props;
+ this._bottom = value;
+ if (enabled) {
+ this.setState({bottom: value});
+ }
+ };
+
_updateBottomIfNecessary = async () => {
if (this._keyboardEvent == null) {
- this.setState({bottom: 0});
+ this._setBottom(0);
return;
}

const {duration, easing, endCoordinates} = this._keyboardEvent;
const height = await this._relativeKeyboardHeight(endCoordinates);

- if (this.state.bottom === height) {
+ if (this._bottom === height) {
return;
}

- if (duration && easing) {
+ this._setBottom(height);
+
+ if (enabled && duration && easing) {
LayoutAnimation.configureNext({
// We have to pass the duration equal to minimal accepted duration defined here: RCTLayoutAnimation.m
duration: duration > 10 ? duration : 10,
@@ -150,9 +164,15 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
},
});
}
- this.setState({bottom: height});
};

+ componentDidUpdate(_: Props, prevState: State): void {
+ const {enabled = true} = this.props;
+ if (enabled && this._bottom !== prevState.bottom) {
+ this.setState({bottom: this._bottom});
+ }
+ }
+
componentDidMount(): void {
if (Platform.OS === 'ios') {
this._subscriptions = [
1 change: 1 addition & 0 deletions src/components/ScreenWrapper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class ScreenWrapper extends React.Component {
<KeyboardAvoidingView
style={[styles.w100, styles.h100, {maxHeight}]}
behavior={this.props.keyboardAvoidingViewBehavior}
enabled={this.props.shouldEnableKeyboardAvoidingView}
>
<PickerAvoidingView
style={styles.flex1}
Expand Down
4 changes: 4 additions & 0 deletions src/components/ScreenWrapper/propTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ const propTypes = {
* Search 'switch(behavior)' in ./node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js for more context */
keyboardAvoidingViewBehavior: PropTypes.oneOf(['padding', 'height', 'position']),

/** Whether KeyboardAvoidingView should be enabled. Use false for screens where this functionality is not necessary */
shouldEnableKeyboardAvoidingView: PropTypes.bool,

/** Whether picker modal avoiding should be enabled. Should be enabled when there's a picker at the bottom of a
* scrollable form, gives a subtly better UX if disabled on non-scrollable screens with a submit button */
shouldEnablePickerAvoiding: PropTypes.bool,
Expand All @@ -47,6 +50,7 @@ const defaultProps = {
includePaddingTop: true,
onEntryTransitionEnd: () => {},
keyboardAvoidingViewBehavior: 'padding',
shouldEnableKeyboardAvoidingView: true,
shouldEnableMaxHeight: false,
shouldEnablePickerAvoiding: true,
shouldShowOfflineIndicator: true,
Expand Down
5 changes: 4 additions & 1 deletion src/pages/home/ReportScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,10 @@ class ReportScreen extends React.Component {
reactionListRef: this.reactionListRef,
}}
>
<ScreenWrapper style={screenWrapperStyle}>
<ScreenWrapper
style={screenWrapperStyle}
shouldEnableKeyboardAvoidingView={this.props.isFocused}
>
<FullPageNotFoundView
shouldShow={(!this.props.report.reportID && !this.props.report.isLoadingReportActions && !isLoading) || shouldHideReport}
subtitleKey="notFound.noAccess"
Expand Down
1 change: 1 addition & 0 deletions src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class BaseSidebarScreen extends Component {
return (
<ScreenWrapper
includeSafeAreaPaddingBottom={false}
shouldEnableKeyboardAvoidingView={false}
style={[styles.sidebar, Browser.isMobile() ? styles.userSelectNone : {}]}
>
{({insets}) => (
Expand Down

0 comments on commit e029bb1

Please sign in to comment.