From 7ca29f856c41305baebae957112b9e7ce7089d02 Mon Sep 17 00:00:00 2001
From: sarious <sarious.w@gmail.com>
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}
                         >
                             <KeyboardAvoidingView
-                                style={[styles.w100, styles.h100, {maxHeight}]}
+                                style={[styles.w100, styles.h100, {maxHeight, minHeight}]}
                                 behavior={keyboardAvoidingViewBehavior}
                                 enabled={shouldEnableKeyboardAvoidingView}
                             >
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) {
         <ScreenWrapper
             includeSafeAreaPaddingBottom={false}
             shouldEnableKeyboardAvoidingView={false}
+            shouldEnableMinHeight={DeviceCapabilities.canUseTouchScreen()}
             headerGapStyles={isDraggingOver ? [styles.receiptDropHeaderGap] : []}
             testID={MoneyRequestSelectorPage.displayName}
         >

From d097f0e7791a97829b28ea60413268133abcbc1d Mon Sep 17 00:00:00 2001
From: sarious <sarious.w@gmail.com>
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 <sarious.w@gmail.com>
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) {
         <ScreenWrapper
             includeSafeAreaPaddingBottom={false}
             shouldEnableKeyboardAvoidingView={false}
-            shouldEnableMinHeight={DeviceCapabilities.canUseTouchScreen()}
+            shouldEnableMinHeight={DeviceCapabilities.canUseTouchScreen() && props.selectedTab === CONST.TAB.MANUAL}
             headerGapStyles={isDraggingOver ? [styles.receiptDropHeaderGap] : []}
             testID={MoneyRequestSelectorPage.displayName}
         >

From df084d5ca160b918e43b5c8fee7e10f3af44df00 Mon Sep 17 00:00:00 2001
From: sarious <sarious.w@gmail.com>
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
         <ScreenWrapper
             includeSafeAreaPaddingBottom={false}
             shouldEnableMaxHeight
+            shouldEnableMinHeight={DeviceCapabilities.canUseTouchScreen()}
             testID={EditRequestAmountPage.displayName}
         >
             <HeaderWithBackButton title={translate('iou.amount')} />

From b2af5ce230d94d50b3c3c1accd33deea03dd0547 Mon Sep 17 00:00:00 2001
From: sarious <sarious.w@gmail.com>
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 <sarious.w@gmail.com>
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) {
         <ScreenWrapper
             includeSafeAreaPaddingBottom={false}
             shouldEnableKeyboardAvoidingView={false}
-            shouldEnableMinHeight={DeviceCapabilities.canUseTouchScreen() && props.selectedTab === CONST.TAB.MANUAL}
+            shouldEnableMinHeight={DeviceCapabilities.canUseTouchScreen()}
             headerGapStyles={isDraggingOver ? [styles.receiptDropHeaderGap] : []}
             testID={MoneyRequestSelectorPage.displayName}
         >

From bbd873790e49fd96f1fe168cb1743b49c1ea78cf Mon Sep 17 00:00:00 2001
From: sarious <sarious.w@gmail.com>
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 <sarious.w@gmail.com>
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,