diff --git a/.eslintignore b/.eslintignore index 5b3bc64e4..cd7e56949 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1002,6 +1002,9 @@ packages/app-mobile/components/SelectDateTimeDialog.js.map packages/app-mobile/components/SideMenu.d.ts packages/app-mobile/components/SideMenu.js packages/app-mobile/components/SideMenu.js.map +packages/app-mobile/components/app-nav.d.ts +packages/app-mobile/components/app-nav.js +packages/app-mobile/components/app-nav.js.map packages/app-mobile/components/TextInput.d.ts packages/app-mobile/components/TextInput.js packages/app-mobile/components/TextInput.js.map diff --git a/.gitignore b/.gitignore index e704d380c..036d71b37 100644 --- a/.gitignore +++ b/.gitignore @@ -990,6 +990,9 @@ packages/app-mobile/components/SelectDateTimeDialog.js.map packages/app-mobile/components/SideMenu.d.ts packages/app-mobile/components/SideMenu.js packages/app-mobile/components/SideMenu.js.map +packages/app-mobile/components/app-nav.d.ts +packages/app-mobile/components/app-nav.js +packages/app-mobile/components/app-nav.js.map packages/app-mobile/components/TextInput.d.ts packages/app-mobile/components/TextInput.js packages/app-mobile/components/TextInput.js.map diff --git a/packages/app-mobile/components/app-nav.js b/packages/app-mobile/components/app-nav.tsx similarity index 55% rename from packages/app-mobile/components/app-nav.js rename to packages/app-mobile/components/app-nav.tsx index 440cf36fe..dc384e8f3 100644 --- a/packages/app-mobile/components/app-nav.js +++ b/packages/app-mobile/components/app-nav.tsx @@ -1,17 +1,37 @@ -const React = require('react'); -const Component = React.Component; -const { connect } = require('react-redux'); +import * as React from 'react'; +import { connect } from 'react-redux'; const { NotesScreen } = require('./screens/notes.js'); const { SearchScreen } = require('./screens/search.js'); -const { KeyboardAvoidingView, Keyboard, Platform, View } = require('react-native'); +import { Component } from 'react'; +import { KeyboardAvoidingView, Keyboard, Platform, View, KeyboardEvent, Dimensions, EmitterSubscription } from 'react-native'; +import { AppState } from '../utils/types'; const { themeStyle } = require('./global-style.js'); -class AppNavComponent extends Component { - constructor() { - super(); +interface State { + autoCompletionBarExtraHeight: number; + floatingKeyboardEnabled: boolean; +} + +interface Props { + route: any; + screens: any; + dispatch: (action: any)=> void; + themeId: number; +} + +class AppNavComponent extends Component { + private previousRouteName_: string|null = null; + private keyboardDidShowListener: EmitterSubscription|null = null; + private keyboardDidHideListener: EmitterSubscription|null = null; + private keyboardWillChangeFrameListener: EmitterSubscription|null = null; + + constructor(props: Props) { + super(props); + this.previousRouteName_ = null; this.state = { autoCompletionBarExtraHeight: 0, // Extra padding for the auto completion bar at the top of the keyboard + floatingKeyboardEnabled: false, }; } @@ -19,14 +39,18 @@ class AppNavComponent extends Component { if (Platform.OS === 'ios') { this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow.bind(this)); this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide.bind(this)); + this.keyboardWillChangeFrameListener = Keyboard.addListener('keyboardWillChangeFrame', this.keyboardWillChangeFrame); } } componentWillUnmount() { - if (this.keyboardDidShowListener) this.keyboardDidShowListener.remove(); - if (this.keyboardDidHideListener) this.keyboardDidHideListener.remove(); + this.keyboardDidShowListener?.remove(); + this.keyboardDidHideListener?.remove(); + this.keyboardWillChangeFrameListener?.remove(); + this.keyboardDidShowListener = null; this.keyboardDidHideListener = null; + this.keyboardWillChangeFrameListener = null; } keyboardDidShow() { @@ -37,6 +61,16 @@ class AppNavComponent extends Component { this.setState({ autoCompletionBarExtraHeight: 0 }); } + keyboardWillChangeFrame = (evt: KeyboardEvent) => { + const windowWidth = Dimensions.get('window').width; + + // If the keyboard isn't as wide as the window, the floating keyboard is diabled. + // See https://github.com/facebook/react-native/issues/29473#issuecomment-696658937 + this.setState({ + floatingKeyboardEnabled: evt.endCoordinates.width < windowWidth, + }); + }; + render() { if (!this.props.route) throw new Error('Route must not be null'); @@ -67,8 +101,17 @@ class AppNavComponent extends Component { const style = { flex: 1, backgroundColor: theme.backgroundColor }; + // When the floating keybaord is enabled, the KeyboardAvoidingView can have a very small + // height. Don't use the KeyboardAvoidingView when the floating keyboard is enabled. + // See https://github.com/facebook/react-native/issues/29473 + const keyboardAvoidingViewEnabled = !this.state.floatingKeyboardEnabled; + return ( - + {searchScreenLoaded && } {!notesScreenVisible && !searchScreenVisible && } @@ -78,7 +121,7 @@ class AppNavComponent extends Component { } } -const AppNav = connect(state => { +const AppNav = connect((state: AppState) => { return { route: state.route, themeId: state.settings.theme,