From 7ca29f856c41305baebae957112b9e7ce7089d02 Mon Sep 17 00:00:00 2001 From: sarious Date: Fri, 20 Oct 2023 13:07:45 +0400 Subject: [PATCH 1/8] Fix 17866: After pressing the back arrow to "Send/Request money" screen, the keyboard flashes --- src/components/ScreenWrapper/index.js | 6 ++- src/hooks/useInitialWindowDimensions/index.js | 50 +++++++++++++++++++ .../index.native.js | 50 +++++++++++++++++++ src/pages/iou/MoneyRequestSelectorPage.js | 2 + 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/hooks/useInitialWindowDimensions/index.js create mode 100644 src/hooks/useInitialWindowDimensions/index.native.js diff --git a/src/components/ScreenWrapper/index.js b/src/components/ScreenWrapper/index.js index e2af40589a8a..ecb83c28759e 100644 --- a/src/components/ScreenWrapper/index.js +++ b/src/components/ScreenWrapper/index.js @@ -16,12 +16,14 @@ import toggleTestToolsModal from '../../libs/actions/TestTool'; import CustomDevMenu from '../CustomDevMenu'; import * as Browser from '../../libs/Browser'; import useWindowDimensions from '../../hooks/useWindowDimensions'; +import useInitialDimensions from '../../hooks/useInitialWindowDimensions'; import useKeyboardState from '../../hooks/useKeyboardState'; import useEnvironment from '../../hooks/useEnvironment'; import useNetwork from '../../hooks/useNetwork'; function ScreenWrapper({ shouldEnableMaxHeight, + shouldEnableMinHeight, includePaddingTop, keyboardAvoidingViewBehavior, includeSafeAreaPaddingBottom, @@ -37,12 +39,14 @@ function ScreenWrapper({ testID, }) { const {windowHeight, isSmallScreenWidth} = useWindowDimensions(); + const {initialHeight} = useInitialDimensions(); const keyboardState = useKeyboardState(); const {isDevelopment} = useEnvironment(); const {isOffline} = useNetwork(); const navigation = useNavigation(); const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false); const maxHeight = shouldEnableMaxHeight ? windowHeight : undefined; + const minHeight = shouldEnableMinHeight ? initialHeight : undefined; const isKeyboardShown = lodashGet(keyboardState, 'isKeyboardShown', false); const panResponder = useRef( @@ -125,7 +129,7 @@ function ScreenWrapper({ {...keyboardDissmissPanResponder.panHandlers} > diff --git a/src/hooks/useInitialWindowDimensions/index.js b/src/hooks/useInitialWindowDimensions/index.js new file mode 100644 index 000000000000..ae498f45377f --- /dev/null +++ b/src/hooks/useInitialWindowDimensions/index.js @@ -0,0 +1,50 @@ +// eslint-disable-next-line no-restricted-imports +import {useState, useEffect} from 'react'; +import {Dimensions} from 'react-native'; + +export default function () { + const [dimensions, setDimensions] = useState(() => { + const window = Dimensions.get('window'); + const screen = Dimensions.get('screen'); + + return { + screenHeight: screen.height, + screenWidth: screen.width, + initialHeight: window.height, + initialWidth: window.width, + }; + }); + + useEffect(() => { + const onDimensionChange = (newDimensions) => { + const {window, screen} = newDimensions; + + setDimensions((oldState) => { + if (screen.width !== oldState.screenWidth || screen.height !== oldState.screenHeight || window.height > oldState.initialHeight) { + return { + initialHeight: window.height, + initialWidth: window.width, + screenHeight: screen.height, + screenWidth: screen.width, + }; + } + + return oldState; + }); + }; + + const dimensionsEventListener = Dimensions.addEventListener('change', onDimensionChange); + + return () => { + if (!dimensionsEventListener) { + return; + } + dimensionsEventListener.remove(); + }; + }, []); + + return { + initialWidth: dimensions.initialWidth, + initialHeight: dimensions.initialHeight, + }; +} diff --git a/src/hooks/useInitialWindowDimensions/index.native.js b/src/hooks/useInitialWindowDimensions/index.native.js new file mode 100644 index 000000000000..ae498f45377f --- /dev/null +++ b/src/hooks/useInitialWindowDimensions/index.native.js @@ -0,0 +1,50 @@ +// eslint-disable-next-line no-restricted-imports +import {useState, useEffect} from 'react'; +import {Dimensions} from 'react-native'; + +export default function () { + const [dimensions, setDimensions] = useState(() => { + const window = Dimensions.get('window'); + const screen = Dimensions.get('screen'); + + return { + screenHeight: screen.height, + screenWidth: screen.width, + initialHeight: window.height, + initialWidth: window.width, + }; + }); + + useEffect(() => { + const onDimensionChange = (newDimensions) => { + const {window, screen} = newDimensions; + + setDimensions((oldState) => { + if (screen.width !== oldState.screenWidth || screen.height !== oldState.screenHeight || window.height > oldState.initialHeight) { + return { + initialHeight: window.height, + initialWidth: window.width, + screenHeight: screen.height, + screenWidth: screen.width, + }; + } + + return oldState; + }); + }; + + const dimensionsEventListener = Dimensions.addEventListener('change', onDimensionChange); + + return () => { + if (!dimensionsEventListener) { + return; + } + dimensionsEventListener.remove(); + }; + }, []); + + return { + initialWidth: dimensions.initialWidth, + initialHeight: dimensions.initialHeight, + }; +} diff --git a/src/pages/iou/MoneyRequestSelectorPage.js b/src/pages/iou/MoneyRequestSelectorPage.js index 0786faa3841b..bcf75bd64056 100644 --- a/src/pages/iou/MoneyRequestSelectorPage.js +++ b/src/pages/iou/MoneyRequestSelectorPage.js @@ -22,6 +22,7 @@ import NewRequestAmountPage from './steps/NewRequestAmountPage'; import reportPropTypes from '../reportPropTypes'; import * as ReportUtils from '../../libs/ReportUtils'; import usePrevious from '../../hooks/usePrevious'; +import * as DeviceCapabilities from '../../libs/DeviceCapabilities'; const propTypes = { /** React Navigation route */ @@ -85,6 +86,7 @@ function MoneyRequestSelectorPage(props) { From d097f0e7791a97829b28ea60413268133abcbc1d Mon Sep 17 00:00:00 2001 From: sarious Date: Fri, 20 Oct 2023 18:36:20 +0400 Subject: [PATCH 2/8] added hook description --- src/hooks/useInitialWindowDimensions/index.js | 5 +++++ src/hooks/useInitialWindowDimensions/index.native.js | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/hooks/useInitialWindowDimensions/index.js b/src/hooks/useInitialWindowDimensions/index.js index ae498f45377f..c568bb8ace38 100644 --- a/src/hooks/useInitialWindowDimensions/index.js +++ b/src/hooks/useInitialWindowDimensions/index.js @@ -2,6 +2,11 @@ import {useState, useEffect} from 'react'; import {Dimensions} from 'react-native'; +/** + * A convenience hook that provides initial size (width and height). + * An initial height allows to know the real height of window, + * while the standard useWindowDimensions hook return the height minus Virtual keyboard height + */ export default function () { const [dimensions, setDimensions] = useState(() => { const window = Dimensions.get('window'); diff --git a/src/hooks/useInitialWindowDimensions/index.native.js b/src/hooks/useInitialWindowDimensions/index.native.js index ae498f45377f..c568bb8ace38 100644 --- a/src/hooks/useInitialWindowDimensions/index.native.js +++ b/src/hooks/useInitialWindowDimensions/index.native.js @@ -2,6 +2,11 @@ import {useState, useEffect} from 'react'; import {Dimensions} from 'react-native'; +/** + * A convenience hook that provides initial size (width and height). + * An initial height allows to know the real height of window, + * while the standard useWindowDimensions hook return the height minus Virtual keyboard height + */ export default function () { const [dimensions, setDimensions] = useState(() => { const window = Dimensions.get('window'); From 6a989ec3eef6798141a68fa2017dc9c379bdc0b0 Mon Sep 17 00:00:00 2001 From: sarious Date: Tue, 24 Oct 2023 17:23:28 +0400 Subject: [PATCH 3/8] apply shouldEnableMinHeight only for Manual tab. added property to propTypes --- src/components/ScreenWrapper/propTypes.js | 3 +++ src/pages/iou/MoneyRequestSelectorPage.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/ScreenWrapper/propTypes.js b/src/components/ScreenWrapper/propTypes.js index 848aa28cde43..3aed26255ec7 100644 --- a/src/components/ScreenWrapper/propTypes.js +++ b/src/components/ScreenWrapper/propTypes.js @@ -37,6 +37,9 @@ const propTypes = { /** Whether to use the maxHeight (true) or use the 100% of the height (false) */ shouldEnableMaxHeight: PropTypes.bool, + /** Whether to use the minHeight. Use true for screens where the window height are changing because of Virtual Keyboard */ + shouldEnableMinHeight: PropTypes.bool, + /** Array of additional styles for header gap */ headerGapStyles: PropTypes.arrayOf(PropTypes.object), diff --git a/src/pages/iou/MoneyRequestSelectorPage.js b/src/pages/iou/MoneyRequestSelectorPage.js index bcf75bd64056..b163d86113a6 100644 --- a/src/pages/iou/MoneyRequestSelectorPage.js +++ b/src/pages/iou/MoneyRequestSelectorPage.js @@ -86,7 +86,7 @@ function MoneyRequestSelectorPage(props) { From df084d5ca160b918e43b5c8fee7e10f3af44df00 Mon Sep 17 00:00:00 2001 From: sarious Date: Tue, 24 Oct 2023 18:16:42 +0400 Subject: [PATCH 4/8] fix the bug with screen width inside the edit money request flow --- src/pages/EditRequestAmountPage.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/EditRequestAmountPage.js b/src/pages/EditRequestAmountPage.js index d65fdafb3b59..661b84b5af3f 100644 --- a/src/pages/EditRequestAmountPage.js +++ b/src/pages/EditRequestAmountPage.js @@ -6,6 +6,7 @@ import useLocalize from '../hooks/useLocalize'; import ScreenWrapper from '../components/ScreenWrapper'; import HeaderWithBackButton from '../components/HeaderWithBackButton'; import MoneyRequestAmountForm from './iou/steps/MoneyRequestAmountForm'; +import * as DeviceCapabilities from '../libs/DeviceCapabilities'; const propTypes = { /** Transaction default amount value */ @@ -43,6 +44,7 @@ function EditRequestAmountPage({defaultAmount, defaultCurrency, onNavigateToCurr From b2af5ce230d94d50b3c3c1accd33deea03dd0547 Mon Sep 17 00:00:00 2001 From: sarious Date: Tue, 24 Oct 2023 18:17:35 +0400 Subject: [PATCH 5/8] fix the bug with bottom inset, when buttons at the bottom are covered by "Home bar" --- src/hooks/useInitialWindowDimensions/index.js | 5 ++++- src/hooks/useInitialWindowDimensions/index.native.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/hooks/useInitialWindowDimensions/index.js b/src/hooks/useInitialWindowDimensions/index.js index c568bb8ace38..d14ed322150f 100644 --- a/src/hooks/useInitialWindowDimensions/index.js +++ b/src/hooks/useInitialWindowDimensions/index.js @@ -1,6 +1,7 @@ // eslint-disable-next-line no-restricted-imports import {useState, useEffect} from 'react'; import {Dimensions} from 'react-native'; +import {initialWindowMetrics} from "react-native-safe-area-context"; /** * A convenience hook that provides initial size (width and height). @@ -48,8 +49,10 @@ export default function () { }; }, []); + const bottomInset = initialWindowMetrics?.insets?.bottom ?? 0; + return { initialWidth: dimensions.initialWidth, - initialHeight: dimensions.initialHeight, + initialHeight: dimensions.initialHeight - bottomInset, }; } diff --git a/src/hooks/useInitialWindowDimensions/index.native.js b/src/hooks/useInitialWindowDimensions/index.native.js index c568bb8ace38..d14ed322150f 100644 --- a/src/hooks/useInitialWindowDimensions/index.native.js +++ b/src/hooks/useInitialWindowDimensions/index.native.js @@ -1,6 +1,7 @@ // eslint-disable-next-line no-restricted-imports import {useState, useEffect} from 'react'; import {Dimensions} from 'react-native'; +import {initialWindowMetrics} from "react-native-safe-area-context"; /** * A convenience hook that provides initial size (width and height). @@ -48,8 +49,10 @@ export default function () { }; }, []); + const bottomInset = initialWindowMetrics?.insets?.bottom ?? 0; + return { initialWidth: dimensions.initialWidth, - initialHeight: dimensions.initialHeight, + initialHeight: dimensions.initialHeight - bottomInset, }; } From 7c2a515a5c4f625b58410790274885490519574b Mon Sep 17 00:00:00 2001 From: sarious Date: Tue, 31 Oct 2023 02:19:51 +0400 Subject: [PATCH 6/8] enabled min height for all tabs --- src/pages/iou/MoneyRequestSelectorPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/MoneyRequestSelectorPage.js b/src/pages/iou/MoneyRequestSelectorPage.js index b163d86113a6..bcf75bd64056 100644 --- a/src/pages/iou/MoneyRequestSelectorPage.js +++ b/src/pages/iou/MoneyRequestSelectorPage.js @@ -86,7 +86,7 @@ function MoneyRequestSelectorPage(props) { From bbd873790e49fd96f1fe168cb1743b49c1ea78cf Mon Sep 17 00:00:00 2001 From: sarious Date: Wed, 1 Nov 2023 02:22:31 +0400 Subject: [PATCH 7/8] use aliases. get rid of useInitialWindowDimensions native file --- .../index.native.js | 58 ------------------- src/pages/EditRequestAmountPage.js | 2 +- src/pages/iou/MoneyRequestSelectorPage.js | 5 +- 3 files changed, 2 insertions(+), 63 deletions(-) delete mode 100644 src/hooks/useInitialWindowDimensions/index.native.js diff --git a/src/hooks/useInitialWindowDimensions/index.native.js b/src/hooks/useInitialWindowDimensions/index.native.js deleted file mode 100644 index d14ed322150f..000000000000 --- a/src/hooks/useInitialWindowDimensions/index.native.js +++ /dev/null @@ -1,58 +0,0 @@ -// eslint-disable-next-line no-restricted-imports -import {useState, useEffect} from 'react'; -import {Dimensions} from 'react-native'; -import {initialWindowMetrics} from "react-native-safe-area-context"; - -/** - * A convenience hook that provides initial size (width and height). - * An initial height allows to know the real height of window, - * while the standard useWindowDimensions hook return the height minus Virtual keyboard height - */ -export default function () { - const [dimensions, setDimensions] = useState(() => { - const window = Dimensions.get('window'); - const screen = Dimensions.get('screen'); - - return { - screenHeight: screen.height, - screenWidth: screen.width, - initialHeight: window.height, - initialWidth: window.width, - }; - }); - - useEffect(() => { - const onDimensionChange = (newDimensions) => { - const {window, screen} = newDimensions; - - setDimensions((oldState) => { - if (screen.width !== oldState.screenWidth || screen.height !== oldState.screenHeight || window.height > oldState.initialHeight) { - return { - initialHeight: window.height, - initialWidth: window.width, - screenHeight: screen.height, - screenWidth: screen.width, - }; - } - - return oldState; - }); - }; - - const dimensionsEventListener = Dimensions.addEventListener('change', onDimensionChange); - - return () => { - if (!dimensionsEventListener) { - return; - } - dimensionsEventListener.remove(); - }; - }, []); - - const bottomInset = initialWindowMetrics?.insets?.bottom ?? 0; - - return { - initialWidth: dimensions.initialWidth, - initialHeight: dimensions.initialHeight - bottomInset, - }; -} diff --git a/src/pages/EditRequestAmountPage.js b/src/pages/EditRequestAmountPage.js index f0e878ccbfba..5fb26e961fad 100644 --- a/src/pages/EditRequestAmountPage.js +++ b/src/pages/EditRequestAmountPage.js @@ -4,9 +4,9 @@ import React, {useCallback, useRef} from 'react'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; +import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import CONST from '@src/CONST'; import MoneyRequestAmountForm from './iou/steps/MoneyRequestAmountForm'; -import * as DeviceCapabilities from '../libs/DeviceCapabilities'; const propTypes = { /** Transaction default amount value */ diff --git a/src/pages/iou/MoneyRequestSelectorPage.js b/src/pages/iou/MoneyRequestSelectorPage.js index 7b7992d28f4e..125a83cd0fd3 100644 --- a/src/pages/iou/MoneyRequestSelectorPage.js +++ b/src/pages/iou/MoneyRequestSelectorPage.js @@ -12,6 +12,7 @@ import TabSelector from '@components/TabSelector/TabSelector'; import useLocalize from '@hooks/useLocalize'; import usePrevious from '@hooks/usePrevious'; import compose from '@libs/compose'; +import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import * as IOUUtils from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; import OnyxTabNavigator, {TopTab} from '@libs/Navigation/OnyxTabNavigator'; @@ -25,10 +26,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import NewDistanceRequestPage from './NewDistanceRequestPage'; import ReceiptSelector from './ReceiptSelector'; import NewRequestAmountPage from './steps/NewRequestAmountPage'; -import reportPropTypes from '@pages/reportPropTypes'; -import * as ReportUtils from '@libs/ReportUtils'; -import usePrevious from '@hooks/usePrevious'; -import * as DeviceCapabilities from '@libs/DeviceCapabilities'; const propTypes = { /** React Navigation route */ From ae9815ce8e35880cb984ca69109b068962034b8e Mon Sep 17 00:00:00 2001 From: sarious Date: Wed, 1 Nov 2023 03:42:48 +0400 Subject: [PATCH 8/8] fix eslint errors. added jsdoc returns line --- src/hooks/useInitialWindowDimensions/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/hooks/useInitialWindowDimensions/index.js b/src/hooks/useInitialWindowDimensions/index.js index d14ed322150f..487b4e498228 100644 --- a/src/hooks/useInitialWindowDimensions/index.js +++ b/src/hooks/useInitialWindowDimensions/index.js @@ -1,12 +1,13 @@ // eslint-disable-next-line no-restricted-imports -import {useState, useEffect} from 'react'; +import {useEffect, useState} from 'react'; import {Dimensions} from 'react-native'; -import {initialWindowMetrics} from "react-native-safe-area-context"; +import {initialWindowMetrics} from 'react-native-safe-area-context'; /** * A convenience hook that provides initial size (width and height). * An initial height allows to know the real height of window, * while the standard useWindowDimensions hook return the height minus Virtual keyboard height + * @returns {Object} with information about initial width and height */ export default function () { const [dimensions, setDimensions] = useState(() => { @@ -49,7 +50,7 @@ export default function () { }; }, []); - const bottomInset = initialWindowMetrics?.insets?.bottom ?? 0; + const bottomInset = initialWindowMetrics && initialWindowMetrics.insets && initialWindowMetrics.insets.bottom ? initialWindowMetrics.insets.bottom : 0; return { initialWidth: dimensions.initialWidth,