From fd5bd2d90d68808be87d1820ba25745632c65c83 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 26 Jul 2023 14:16:51 -0700
Subject: [PATCH 01/39] Separate DistanceRequestPage to pass transactionID

---
 src/pages/iou/DistanceRequestPage.js | 87 ++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)
 create mode 100644 src/pages/iou/DistanceRequestPage.js

diff --git a/src/pages/iou/DistanceRequestPage.js b/src/pages/iou/DistanceRequestPage.js
new file mode 100644
index 000000000000..ee65787050bc
--- /dev/null
+++ b/src/pages/iou/DistanceRequestPage.js
@@ -0,0 +1,87 @@
+import React, {useEffect} from 'react';
+import PropTypes from 'prop-types';
+import {withOnyx} from 'react-native-onyx';
+import * as IOU from '../../libs/actions/IOU';
+import ONYXKEYS from '../../ONYXKEYS';
+import DistanceRequest from '../../components/DistanceRequest';
+import CONST from '../../CONST';
+import reportPropTypes from '../reportPropTypes';
+
+const propTypes = {
+    /** The transactionID of this request */
+    transactionID: PropTypes.string,
+
+    /** Route params */
+    route: PropTypes.shape({
+        params: PropTypes.shape({
+            iouType: PropTypes.string,
+            reportID: PropTypes.string,
+        }),
+    }),
+
+    /** The report on which the request is initiated on */
+    report: reportPropTypes,
+
+    /** Holds data related to Money Request view state, rather than the underlying Money Request data. */
+    iou: PropTypes.shape({
+        id: PropTypes.string,
+        amount: PropTypes.number,
+        currency: PropTypes.string,
+        participants: PropTypes.arrayOf(
+            PropTypes.shape({
+                accountID: PropTypes.number,
+                login: PropTypes.string,
+                isPolicyExpenseChat: PropTypes.bool,
+                isOwnPolicyExpenseChat: PropTypes.bool,
+                selected: PropTypes.bool,
+            }),
+        ),
+        transactionID: PropTypes.string,
+    }),
+};
+
+const defaultProps = {
+    transactionID: '',
+    route: {
+        params: {
+            iouType: '',
+            reportID: '',
+        },
+    },
+    report: {},
+    iou: {
+        id: '',
+        amount: 0,
+        currency: CONST.CURRENCY.USD,
+        participants: [],
+        transactionID: '',
+    },
+};
+
+function DistanceRequestPage({route, report, iou, transactionID}) {
+    useEffect(() => {
+        if (transactionID) {
+            return;
+        }
+        IOU.createEmptyTransaction();
+    }, [transactionID]);
+
+
+    return (
+        <DistanceRequest
+            route={route}
+            report={report}
+            iou={iou}
+            transactionID={transactionID}
+        />
+    );
+}
+
+DistanceRequestPage.displayName = 'DistanceRequestPage';
+DistanceRequestPage.propTypes = propTypes;
+DistanceRequestPage.defaultProps = defaultProps;
+export default withOnyx({
+    // We must provide a default value for transactionID here, otherwise the component won't mount
+    // because withOnyx returns null until all the keys are defined
+    transactionID: {key: ONYXKEYS.IOU, selector: (iou) => iou && iou.transactionID || ''},
+})(DistanceRequestPage);

From ed1677ad3d230378e66899b37cb02c40f820c2c2 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 26 Jul 2023 14:19:43 -0700
Subject: [PATCH 02/39] Action to create initial waypoints

---
 src/libs/actions/Transaction.js | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 src/libs/actions/Transaction.js

diff --git a/src/libs/actions/Transaction.js b/src/libs/actions/Transaction.js
new file mode 100644
index 000000000000..7566f950d728
--- /dev/null
+++ b/src/libs/actions/Transaction.js
@@ -0,0 +1,11 @@
+import Onyx from 'react-native-onyx';
+import ONYXKEYS from '../../ONYXKEYS';
+
+function createInitialWaypoints(transactionID) {
+    Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {
+        'waypoint0': {},
+        'waypoint1': {},
+    });
+}
+
+export default createInitialWaypoints;
\ No newline at end of file

From 18bf82c8659f128af81e13ceda7364a3bde5fe50 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 26 Jul 2023 14:20:26 -0700
Subject: [PATCH 03/39] Connect to transaction and create waypoints

---
 src/components/DistanceRequest.js | 31 ++++++++++++++++++++++++-------
 src/libs/actions/IOU.js           |  2 +-
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 7b8333ab3ae3..4d10e6db93bd 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -1,33 +1,50 @@
 import React, {useEffect} from 'react';
 import {View} from 'react-native';
+import lodashGet from 'lodash/get';
+import _ from 'underscore';
 import PropTypes from 'prop-types';
 import {withOnyx} from 'react-native-onyx';
 import Text from './Text';
-import * as IOU from '../libs/actions/IOU';
 import styles from '../styles/styles';
 import ONYXKEYS from '../ONYXKEYS';
+import createInitialWaypoints from '../libs/actions/Transaction';
 
 const propTypes = {
     /** The transactionID of this request */
     transactionID: PropTypes.string,
+
+    /** The optimistic transaction for this request */
+    transaction: PropTypes.shape({
+        transactionID: PropTypes.string,
+        comment: PropTypes.shape({
+            waypoints: PropTypes.shape({
+                lat: PropTypes.number,
+                lng: PropTypes.number,
+                address: PropTypes.string,
+            })
+        }),
+    }),
 };
 
 const defaultProps = {
     transactionID: '',
+    transaction: {},
 };
 
-function DistanceRequest(props) {
+function DistanceRequest({transaction, transactionID}) {
     useEffect(() => {
-        if (props.transactionID) {
+        const waypoints = lodashGet(transaction, 'comment.waypoints');
+        if (!transaction.transactionID || !_.isEmpty(waypoints)) {
             return;
         }
-        IOU.createEmptyTransaction();
-    }, [props.transactionID]);
+        // Create the initial start and stop waypoints
+        createInitialWaypoints(transaction.transactionID);
+    }, [transaction]);
 
     return (
         <View style={[styles.flex1, styles.flexColumn, styles.w100, styles.alignItemsCenter, styles.mt4]}>
             <Text>Distance Request</Text>
-            <Text>transactionID: {props.transactionID}</Text>
+            <Text>transactionID: {transactionID}</Text>
         </View>
     );
 }
@@ -36,5 +53,5 @@ DistanceRequest.displayName = 'DistanceRequest';
 DistanceRequest.propTypes = propTypes;
 DistanceRequest.defaultProps = defaultProps;
 export default withOnyx({
-    transactionID: {key: ONYXKEYS.IOU, selector: (iou) => iou.transactionID},
+    transaction: {key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}`, selector: (transaction) => ({transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}})},
 })(DistanceRequest);
diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js
index 468a6f3582db..004405241c0d 100644
--- a/src/libs/actions/IOU.js
+++ b/src/libs/actions/IOU.js
@@ -1403,7 +1403,7 @@ function setMoneyRequestReceipt(receiptPath, receiptSource) {
 
 function createEmptyTransaction() {
     const transactionID = NumberUtils.rand64();
-    Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {});
+    Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {transactionID});
     Onyx.merge(ONYXKEYS.IOU, {transactionID});
 }
 

From 6d3820afb933e306dc5f6dd80ca6c6ce3fabaecb Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 26 Jul 2023 14:20:38 -0700
Subject: [PATCH 04/39] Use distance request page

---
 src/pages/iou/MoneyRequestSelectorPage.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/pages/iou/MoneyRequestSelectorPage.js b/src/pages/iou/MoneyRequestSelectorPage.js
index e141501f1afe..be2841342051 100644
--- a/src/pages/iou/MoneyRequestSelectorPage.js
+++ b/src/pages/iou/MoneyRequestSelectorPage.js
@@ -21,7 +21,7 @@ import MoneyRequestAmountPage from './steps/MoneyRequestAmountPage';
 import ReceiptSelector from './ReceiptSelector';
 import DragAndDrop from '../../components/DragAndDrop';
 import * as IOU from '../../libs/actions/IOU';
-import DistanceRequest from '../../components/DistanceRequest';
+import DistanceRequestPage from './DistanceRequestPage';
 import reportPropTypes from '../reportPropTypes';
 import NavigateToNextIOUPage from './NavigateToNextIOUPage';
 import AttachmentUtils from '../../libs/AttachmentUtils';
@@ -152,7 +152,7 @@ function MoneyRequestSelectorPage({route, report, tabSelected, iou, currentUserP
                                 />
                             )}
                             {selectedTab === CONST.TAB.TAB_DISTANCE && (
-                                <DistanceRequest
+                                <DistanceRequestPage
                                     route={route}
                                     report={report}
                                     iou={iou}

From 35bfb2bd1cb5e97ca34280bc5be66e22c9db72eb Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 28 Jul 2023 18:46:10 -0700
Subject: [PATCH 05/39] Store waypoints under comment as intended

---
 src/libs/actions/Transaction.js | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/libs/actions/Transaction.js b/src/libs/actions/Transaction.js
index 7566f950d728..a6f693e6165e 100644
--- a/src/libs/actions/Transaction.js
+++ b/src/libs/actions/Transaction.js
@@ -3,9 +3,14 @@ import ONYXKEYS from '../../ONYXKEYS';
 
 function createInitialWaypoints(transactionID) {
     Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {
-        'waypoint0': {},
-        'waypoint1': {},
+        comment: {
+            waypoints: {
+                'waypoint0': {},
+                'waypoint1': {},
+            }
+        }
     });
+
 }
 
 export default createInitialWaypoints;
\ No newline at end of file

From 4093ecc27a818a3bd0f83169242447c9c367339b Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 28 Jul 2023 18:47:11 -0700
Subject: [PATCH 06/39] Add secondary icon for waypoint menu items

---
 src/components/MenuItem.js          | 18 ++++++++++++++++++
 src/components/menuItemPropTypes.js |  6 ++++++
 2 files changed, 24 insertions(+)

diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js
index 2860b7cef35c..f9c8db7e09ef 100644
--- a/src/components/MenuItem.js
+++ b/src/components/MenuItem.js
@@ -45,12 +45,14 @@ const defaultProps = {
     descriptionTextStyle: styles.breakWord,
     success: false,
     icon: undefined,
+    secondaryIcon: undefined,
     iconWidth: undefined,
     iconHeight: undefined,
     description: undefined,
     iconRight: Expensicons.ArrowRight,
     iconStyles: [],
     iconFill: undefined,
+    secondaryIconFill: undefined,
     focused: false,
     disabled: false,
     isSelected: false,
@@ -194,6 +196,22 @@ function MenuItem(props) {
                                             )}
                                         </View>
                                     )}
+                                    {Boolean(props.secondaryIcon) && (
+                                        <View style={[styles.popoverMenuIcon, ...props.iconStyles]}>
+                                            <Icon
+                                                src={props.secondaryIcon}
+                                                width={props.iconWidth}
+                                                height={props.iconHeight}
+                                                fill={
+                                                    props.secondaryIconFill ||
+                                                    StyleUtils.getIconFillColor(
+                                                        getButtonState(props.focused || isHovered, pressed, props.success, props.disabled, props.interactive),
+                                                        true,
+                                                    )
+                                                }
+                                            />
+                                        </View>
+                                    )}
                                     <View style={[styles.justifyContentCenter, styles.flex1, StyleUtils.getMenuItemTextContainerStyle(props.isSmallAvatarSubscriptMenu)]}>
                                         {Boolean(props.description) && props.shouldShowDescriptionOnTop && (
                                             <Text
diff --git a/src/components/menuItemPropTypes.js b/src/components/menuItemPropTypes.js
index 2a9398c96554..a6424518478c 100644
--- a/src/components/menuItemPropTypes.js
+++ b/src/components/menuItemPropTypes.js
@@ -24,6 +24,9 @@ const propTypes = {
     /** Icon to display on the left side of component */
     icon: PropTypes.oneOfType([PropTypes.elementType, PropTypes.string, PropTypes.arrayOf(avatarPropTypes)]),
 
+    /** Secondary icon to display on the left side of component, right of the icon */
+    secondaryIcon: PropTypes.elementType,
+
     /** Icon Width */
     iconWidth: PropTypes.number,
 
@@ -72,6 +75,9 @@ const propTypes = {
     /** The fill color to pass into the icon. */
     iconFill: PropTypes.string,
 
+    /** The fill color to pass into the secondary icon. */
+    secondaryIconFill: PropTypes.string,
+
     /** Whether item is focused or active */
     focused: PropTypes.bool,
 

From d535699e0500fd1379706465ac12250d53b2ffd1 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 28 Jul 2023 18:47:35 -0700
Subject: [PATCH 07/39] WIP display initial waypoints

---
 src/components/DistanceRequest.js | 43 ++++++++++++++++++++++++-------
 src/languages/en.js               |  7 +++++
 2 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 4d10e6db93bd..c00c57f1687e 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -1,13 +1,18 @@
 import React, {useEffect} from 'react';
-import {View} from 'react-native';
+import {ScrollView } from 'react-native';
 import lodashGet from 'lodash/get';
 import _ from 'underscore';
 import PropTypes from 'prop-types';
 import {withOnyx} from 'react-native-onyx';
 import Text from './Text';
-import styles from '../styles/styles';
 import ONYXKEYS from '../ONYXKEYS';
 import createInitialWaypoints from '../libs/actions/Transaction';
+import MenuItemWithTopDescription from './MenuItemWithTopDescription';
+import withLocalize, {withLocalizePropTypes} from './withLocalize';
+import compose from '../libs/compose';
+import * as Expensicons from './Icon/Expensicons';
+import theme from '../styles/themes/default';
+
 
 const propTypes = {
     /** The transactionID of this request */
@@ -24,6 +29,8 @@ const propTypes = {
             })
         }),
     }),
+
+    ...withLocalizePropTypes,
 };
 
 const defaultProps = {
@@ -31,27 +38,43 @@ const defaultProps = {
     transaction: {},
 };
 
-function DistanceRequest({transaction, transactionID}) {
+function DistanceRequest({transaction, transactionID, translate}) {
+    const waypoints = lodashGet(transaction, 'comment.waypoints');
+
     useEffect(() => {
-        const waypoints = lodashGet(transaction, 'comment.waypoints');
         if (!transaction.transactionID || !_.isEmpty(waypoints)) {
             return;
         }
         // Create the initial start and stop waypoints
         createInitialWaypoints(transaction.transactionID);
-    }, [transaction]);
+    }, [transaction.transactionID, waypoints]);
 
     return (
-        <View style={[styles.flex1, styles.flexColumn, styles.w100, styles.alignItemsCenter, styles.mt4]}>
+        <ScrollView>
+            {_.map(waypoints, (waypoint, index) => {
+                let titleKey = 'distance.waypointTitle.';
+                if (index === 0) {
+                    titleKey += 'start';
+                } else if (index === waypoints.length - 1) {
+                    titleKey += 'finish';
+                } else {
+                    titleKey += 'stop';
+                }
+
+                return <MenuItemWithTopDescription title={translate(titleKey)} icon={Expensicons.Menu} secondaryIcon={Expensicons.DotIndicator} secondaryIconFill={theme.icon}/>;
+            })}
             <Text>Distance Request</Text>
             <Text>transactionID: {transactionID}</Text>
-        </View>
+        </ScrollView>
     );
 }
 
 DistanceRequest.displayName = 'DistanceRequest';
 DistanceRequest.propTypes = propTypes;
 DistanceRequest.defaultProps = defaultProps;
-export default withOnyx({
-    transaction: {key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}`, selector: (transaction) => ({transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}})},
-})(DistanceRequest);
+export default compose(
+    withLocalize,
+    withOnyx({
+        transaction: {key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}`, selector: (transaction) => ({transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}})},
+    })
+)(DistanceRequest);
diff --git a/src/languages/en.js b/src/languages/en.js
index 7d287f67a90c..c6340c0904cb 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -1545,4 +1545,11 @@ export default {
         levelTwoResult: 'Message hidden from channel, plus anonymous warning and message is reported for review.',
         levelThreeResult: 'Message removed from channel plus anonymous warning and message is reported for review.',
     },
+    distance: {
+        waypointTitle: {
+            start: 'Start',
+            finish: 'Finish',
+            stop: 'Stop',
+        },
+    }
 };

From 4b8e4e85c4d559694b462630f761fb76602dcc7e Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 28 Jul 2023 18:59:30 -0700
Subject: [PATCH 08/39] Fix dynamic waypoint title from key

---
 src/components/DistanceRequest.js | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index c00c57f1687e..1c8064799e36 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -39,7 +39,8 @@ const defaultProps = {
 };
 
 function DistanceRequest({transaction, transactionID, translate}) {
-    const waypoints = lodashGet(transaction, 'comment.waypoints');
+    const waypoints = lodashGet(transaction, 'comment.waypoints', {}) ;
+    const lastWaypointIndex = _.size(waypoints) - 1;
 
     useEffect(() => {
         if (!transaction.transactionID || !_.isEmpty(waypoints)) {
@@ -51,11 +52,13 @@ function DistanceRequest({transaction, transactionID, translate}) {
 
     return (
         <ScrollView>
-            {_.map(waypoints, (waypoint, index) => {
+            {_.map(waypoints, (waypoint, key) => {
+                // key is of the form waypoint0, waypoint1, ...
+                const index = Number(key.replace('waypoint', ''));
                 let titleKey = 'distance.waypointTitle.';
                 if (index === 0) {
                     titleKey += 'start';
-                } else if (index === waypoints.length - 1) {
+                } else if (index === lastWaypointIndex) {
                     titleKey += 'finish';
                 } else {
                     titleKey += 'stop';

From 1a1e7d212f89f42aa6e57cfcba5eefa6fbe94fdc Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 28 Jul 2023 19:06:01 -0700
Subject: [PATCH 09/39] Set waypoint description instead of title

---
 src/components/DistanceRequest.js | 10 +++++-----
 src/languages/en.js               |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 1c8064799e36..12664d611e08 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -55,16 +55,16 @@ function DistanceRequest({transaction, transactionID, translate}) {
             {_.map(waypoints, (waypoint, key) => {
                 // key is of the form waypoint0, waypoint1, ...
                 const index = Number(key.replace('waypoint', ''));
-                let titleKey = 'distance.waypointTitle.';
+                let descriptionKey = 'distance.waypointDescription.';
                 if (index === 0) {
-                    titleKey += 'start';
+                    descriptionKey += 'start';
                 } else if (index === lastWaypointIndex) {
-                    titleKey += 'finish';
+                    descriptionKey += 'finish';
                 } else {
-                    titleKey += 'stop';
+                    descriptionKey += 'stop';
                 }
 
-                return <MenuItemWithTopDescription title={translate(titleKey)} icon={Expensicons.Menu} secondaryIcon={Expensicons.DotIndicator} secondaryIconFill={theme.icon}/>;
+                return <MenuItemWithTopDescription description={translate(descriptionKey)} icon={Expensicons.Menu} secondaryIcon={Expensicons.DotIndicator} secondaryIconFill={theme.icon} shouldShowRightIcon/>;
             })}
             <Text>Distance Request</Text>
             <Text>transactionID: {transactionID}</Text>
diff --git a/src/languages/en.js b/src/languages/en.js
index c6340c0904cb..50f3ab9f2e4e 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -1546,7 +1546,7 @@ export default {
         levelThreeResult: 'Message removed from channel plus anonymous warning and message is reported for review.',
     },
     distance: {
-        waypointTitle: {
+        waypointDescription: {
             start: 'Start',
             finish: 'Finish',
             stop: 'Stop',

From 23b584ff83829a8b57853a08b4f3e690bdb34cd2 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 28 Jul 2023 19:07:27 -0700
Subject: [PATCH 10/39] Style

---
 src/components/DistanceRequest.js    | 24 +++++++++++++++++-------
 src/components/MenuItem.js           |  5 +----
 src/languages/en.js                  |  2 +-
 src/libs/actions/Transaction.js      | 11 +++++------
 src/pages/iou/DistanceRequestPage.js |  3 +--
 5 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 12664d611e08..b6df936426c8 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -1,5 +1,5 @@
 import React, {useEffect} from 'react';
-import {ScrollView } from 'react-native';
+import {ScrollView} from 'react-native';
 import lodashGet from 'lodash/get';
 import _ from 'underscore';
 import PropTypes from 'prop-types';
@@ -13,7 +13,6 @@ import compose from '../libs/compose';
 import * as Expensicons from './Icon/Expensicons';
 import theme from '../styles/themes/default';
 
-
 const propTypes = {
     /** The transactionID of this request */
     transactionID: PropTypes.string,
@@ -26,7 +25,7 @@ const propTypes = {
                 lat: PropTypes.number,
                 lng: PropTypes.number,
                 address: PropTypes.string,
-            })
+            }),
         }),
     }),
 
@@ -39,7 +38,7 @@ const defaultProps = {
 };
 
 function DistanceRequest({transaction, transactionID, translate}) {
-    const waypoints = lodashGet(transaction, 'comment.waypoints', {}) ;
+    const waypoints = lodashGet(transaction, 'comment.waypoints', {});
     const lastWaypointIndex = _.size(waypoints) - 1;
 
     useEffect(() => {
@@ -64,7 +63,15 @@ function DistanceRequest({transaction, transactionID, translate}) {
                     descriptionKey += 'stop';
                 }
 
-                return <MenuItemWithTopDescription description={translate(descriptionKey)} icon={Expensicons.Menu} secondaryIcon={Expensicons.DotIndicator} secondaryIconFill={theme.icon} shouldShowRightIcon/>;
+                return (
+                    <MenuItemWithTopDescription
+                        description={translate(descriptionKey)}
+                        icon={Expensicons.Menu}
+                        secondaryIcon={Expensicons.DotIndicator}
+                        secondaryIconFill={theme.icon}
+                        shouldShowRightIcon
+                    />
+                );
             })}
             <Text>Distance Request</Text>
             <Text>transactionID: {transactionID}</Text>
@@ -78,6 +85,9 @@ DistanceRequest.defaultProps = defaultProps;
 export default compose(
     withLocalize,
     withOnyx({
-        transaction: {key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}`, selector: (transaction) => ({transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}})},
-    })
+        transaction: {
+            key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}`,
+            selector: (transaction) => ({transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}}),
+        },
+    }),
 )(DistanceRequest);
diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js
index f9c8db7e09ef..f3d564b78a64 100644
--- a/src/components/MenuItem.js
+++ b/src/components/MenuItem.js
@@ -204,10 +204,7 @@ function MenuItem(props) {
                                                 height={props.iconHeight}
                                                 fill={
                                                     props.secondaryIconFill ||
-                                                    StyleUtils.getIconFillColor(
-                                                        getButtonState(props.focused || isHovered, pressed, props.success, props.disabled, props.interactive),
-                                                        true,
-                                                    )
+                                                    StyleUtils.getIconFillColor(getButtonState(props.focused || isHovered, pressed, props.success, props.disabled, props.interactive), true)
                                                 }
                                             />
                                         </View>
diff --git a/src/languages/en.js b/src/languages/en.js
index 50f3ab9f2e4e..fa52ee4b4846 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -1551,5 +1551,5 @@ export default {
             finish: 'Finish',
             stop: 'Stop',
         },
-    }
+    },
 };
diff --git a/src/libs/actions/Transaction.js b/src/libs/actions/Transaction.js
index a6f693e6165e..b5d9ec4bc680 100644
--- a/src/libs/actions/Transaction.js
+++ b/src/libs/actions/Transaction.js
@@ -5,12 +5,11 @@ function createInitialWaypoints(transactionID) {
     Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {
         comment: {
             waypoints: {
-                'waypoint0': {},
-                'waypoint1': {},
-            }
-        }
+                waypoint0: {},
+                waypoint1: {},
+            },
+        },
     });
-
 }
 
-export default createInitialWaypoints;
\ No newline at end of file
+export default createInitialWaypoints;
diff --git a/src/pages/iou/DistanceRequestPage.js b/src/pages/iou/DistanceRequestPage.js
index ee65787050bc..9284975d4a27 100644
--- a/src/pages/iou/DistanceRequestPage.js
+++ b/src/pages/iou/DistanceRequestPage.js
@@ -66,7 +66,6 @@ function DistanceRequestPage({route, report, iou, transactionID}) {
         IOU.createEmptyTransaction();
     }, [transactionID]);
 
-
     return (
         <DistanceRequest
             route={route}
@@ -83,5 +82,5 @@ DistanceRequestPage.defaultProps = defaultProps;
 export default withOnyx({
     // We must provide a default value for transactionID here, otherwise the component won't mount
     // because withOnyx returns null until all the keys are defined
-    transactionID: {key: ONYXKEYS.IOU, selector: (iou) => iou && iou.transactionID || ''},
+    transactionID: {key: ONYXKEYS.IOU, selector: (iou) => (iou && iou.transactionID) || ''},
 })(DistanceRequestPage);

From c24b2484a247d8bd5fc5c27fa5ea2fa452a7938c Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 2 Aug 2023 09:31:49 -0500
Subject: [PATCH 11/39] WIP add stop button

---
 src/components/DistanceRequest.js | 15 +++++++++++----
 src/languages/en.js               |  1 +
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index b6df936426c8..7a2e7c45e288 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -4,7 +4,6 @@ import lodashGet from 'lodash/get';
 import _ from 'underscore';
 import PropTypes from 'prop-types';
 import {withOnyx} from 'react-native-onyx';
-import Text from './Text';
 import ONYXKEYS from '../ONYXKEYS';
 import createInitialWaypoints from '../libs/actions/Transaction';
 import MenuItemWithTopDescription from './MenuItemWithTopDescription';
@@ -12,6 +11,8 @@ import withLocalize, {withLocalizePropTypes} from './withLocalize';
 import compose from '../libs/compose';
 import * as Expensicons from './Icon/Expensicons';
 import theme from '../styles/themes/default';
+import Button from './Button';
+import styles from '../styles/styles';
 
 const propTypes = {
     /** The transactionID of this request */
@@ -37,7 +38,7 @@ const defaultProps = {
     transaction: {},
 };
 
-function DistanceRequest({transaction, transactionID, translate}) {
+function DistanceRequest({transaction, translate}) {
     const waypoints = lodashGet(transaction, 'comment.waypoints', {});
     const lastWaypointIndex = _.size(waypoints) - 1;
 
@@ -73,8 +74,14 @@ function DistanceRequest({transaction, transactionID, translate}) {
                     />
                 );
             })}
-            <Text>Distance Request</Text>
-            <Text>transactionID: {transactionID}</Text>
+            <Button
+                small
+                icon={Expensicons.Plus}
+                onPress={() => {}}
+                text={translate('distance.addStop')}
+                isDisabled={false}
+                style={[styles.w50]}
+            />
         </ScrollView>
     );
 }
diff --git a/src/languages/en.js b/src/languages/en.js
index fa52ee4b4846..b1a585c11578 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -1546,6 +1546,7 @@ export default {
         levelThreeResult: 'Message removed from channel plus anonymous warning and message is reported for review.',
     },
     distance: {
+        addStop: 'Add stop',
         waypointDescription: {
             start: 'Start',
             finish: 'Finish',

From c50f08397d295e19798b983bbc68dda469d447bd Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 2 Aug 2023 12:39:26 -0500
Subject: [PATCH 12/39] Center button and set proper size

---
 src/components/DistanceRequest.js | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 7a2e7c45e288..626f990373bf 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -1,5 +1,5 @@
 import React, {useEffect} from 'react';
-import {ScrollView} from 'react-native';
+import {ScrollView, View} from 'react-native';
 import lodashGet from 'lodash/get';
 import _ from 'underscore';
 import PropTypes from 'prop-types';
@@ -74,14 +74,16 @@ function DistanceRequest({transaction, translate}) {
                     />
                 );
             })}
-            <Button
-                small
-                icon={Expensicons.Plus}
-                onPress={() => {}}
-                text={translate('distance.addStop')}
-                isDisabled={false}
-                style={[styles.w50]}
-            />
+            <View style={[styles.flexRow, styles.justifyContentCenter]}>
+                <Button
+                    small
+                    icon={Expensicons.Plus}
+                    onPress={() => {}}
+                    text={translate('distance.addStop')}
+                    isDisabled={false}
+                    innerStyles={[styles.ph10]}
+                />
+            </View>
         </ScrollView>
     );
 }

From 5a52842609dca2e1920ce2a0b0af2294746d25f5 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 2 Aug 2023 12:50:46 -0500
Subject: [PATCH 13/39] Add a new waypoint when add stop is pressed

---
 src/components/DistanceRequest.js |  8 ++++----
 src/libs/actions/Transaction.js   | 21 ++++++++++++++++++++-
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 626f990373bf..70da1e1ac6e8 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -5,7 +5,7 @@ import _ from 'underscore';
 import PropTypes from 'prop-types';
 import {withOnyx} from 'react-native-onyx';
 import ONYXKEYS from '../ONYXKEYS';
-import createInitialWaypoints from '../libs/actions/Transaction';
+import * as Transaction from '../libs/actions/Transaction';
 import MenuItemWithTopDescription from './MenuItemWithTopDescription';
 import withLocalize, {withLocalizePropTypes} from './withLocalize';
 import compose from '../libs/compose';
@@ -38,7 +38,7 @@ const defaultProps = {
     transaction: {},
 };
 
-function DistanceRequest({transaction, translate}) {
+function DistanceRequest({transactionID, transaction, translate}) {
     const waypoints = lodashGet(transaction, 'comment.waypoints', {});
     const lastWaypointIndex = _.size(waypoints) - 1;
 
@@ -47,7 +47,7 @@ function DistanceRequest({transaction, translate}) {
             return;
         }
         // Create the initial start and stop waypoints
-        createInitialWaypoints(transaction.transactionID);
+        Transaction.createInitialWaypoints(transaction.transactionID);
     }, [transaction.transactionID, waypoints]);
 
     return (
@@ -78,7 +78,7 @@ function DistanceRequest({transaction, translate}) {
                 <Button
                     small
                     icon={Expensicons.Plus}
-                    onPress={() => {}}
+                    onPress={() => Transaction.addStop(transactionID, lastWaypointIndex + 1)}
                     text={translate('distance.addStop')}
                     isDisabled={false}
                     innerStyles={[styles.ph10]}
diff --git a/src/libs/actions/Transaction.js b/src/libs/actions/Transaction.js
index b5d9ec4bc680..98e0328fa160 100644
--- a/src/libs/actions/Transaction.js
+++ b/src/libs/actions/Transaction.js
@@ -1,6 +1,9 @@
 import Onyx from 'react-native-onyx';
 import ONYXKEYS from '../../ONYXKEYS';
 
+/**
+ * @param {String} transactionID
+ */
 function createInitialWaypoints(transactionID) {
     Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {
         comment: {
@@ -12,4 +15,20 @@ function createInitialWaypoints(transactionID) {
     });
 }
 
-export default createInitialWaypoints;
+/**
+ * Add a stop which is a new waypoint at the newLastIndex
+ *
+ * @param {String} transactionID
+ * @param {Number} newLastIndex
+ */
+function addStop(transactionID, newLastIndex) {
+    Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {
+        comment: {
+            waypoints: {
+                [`waypoint${newLastIndex}`]: {},
+            },
+        },
+    });
+}
+
+export {addStop, createInitialWaypoints};

From abdc2427cead660a1dd9f1e1538a44db2f1e14ea Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 2 Aug 2023 13:54:59 -0500
Subject: [PATCH 14/39] Show only 4 waypoints max in scroll view

---
 src/components/DistanceRequest.js | 72 ++++++++++++++++++++-----------
 1 file changed, 47 insertions(+), 25 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 70da1e1ac6e8..4f97c212eb98 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -1,4 +1,4 @@
-import React, {useEffect} from 'react';
+import React, {useEffect, useRef, useState} from 'react';
 import {ScrollView, View} from 'react-native';
 import lodashGet from 'lodash/get';
 import _ from 'underscore';
@@ -50,31 +50,53 @@ function DistanceRequest({transactionID, transaction, translate}) {
         Transaction.createInitialWaypoints(transaction.transactionID);
     }, [transaction.transactionID, waypoints]);
 
+    const firstMenuItem = useRef(null);
+    const [menuItemHeight, setMenuItemHeight] = useState(0);
+    const measureMenuItemHeight = () => {
+        if (!firstMenuItem.current) {
+            return;
+        }
+        firstMenuItem.current.measure((x, y, width, height) => {
+            setMenuItemHeight(height);
+        });
+    };
+
+    // Show 4 waypoints plus 1/2 of one
+    const scrollContainerHeight = menuItemHeight * 4 + Math.floor(menuItemHeight / 2);
     return (
-        <ScrollView>
-            {_.map(waypoints, (waypoint, key) => {
-                // key is of the form waypoint0, waypoint1, ...
-                const index = Number(key.replace('waypoint', ''));
-                let descriptionKey = 'distance.waypointDescription.';
-                if (index === 0) {
-                    descriptionKey += 'start';
-                } else if (index === lastWaypointIndex) {
-                    descriptionKey += 'finish';
-                } else {
-                    descriptionKey += 'stop';
-                }
+        <>
+            <View style={{height: scrollContainerHeight}}>
+                <ScrollView>
+                    {_.map(waypoints, (waypoint, key) => {
+                        // key is of the form waypoint0, waypoint1, ...
+                        const index = Number(key.replace('waypoint', ''));
+                        let descriptionKey = 'distance.waypointDescription.';
+                        if (index === 0) {
+                            descriptionKey += 'start';
+                        } else if (index === lastWaypointIndex) {
+                            descriptionKey += 'finish';
+                        } else {
+                            descriptionKey += 'stop';
+                        }
 
-                return (
-                    <MenuItemWithTopDescription
-                        description={translate(descriptionKey)}
-                        icon={Expensicons.Menu}
-                        secondaryIcon={Expensicons.DotIndicator}
-                        secondaryIconFill={theme.icon}
-                        shouldShowRightIcon
-                    />
-                );
-            })}
-            <View style={[styles.flexRow, styles.justifyContentCenter]}>
+                        return (
+                            <View
+                                onLayout={index === 0 ? measureMenuItemHeight : null}
+                                ref={index === 0 ? firstMenuItem : null}
+                            >
+                                <MenuItemWithTopDescription
+                                    description={translate(descriptionKey)}
+                                    icon={Expensicons.Menu}
+                                    secondaryIcon={Expensicons.DotIndicator}
+                                    secondaryIconFill={theme.icon}
+                                    shouldShowRightIcon
+                                />
+                            </View>
+                        );
+                    })}
+                </ScrollView>
+            </View>
+            <View style={[styles.flexRow, styles.justifyContentCenter, styles.pt1]}>
                 <Button
                     small
                     icon={Expensicons.Plus}
@@ -84,7 +106,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
                     innerStyles={[styles.ph10]}
                 />
             </View>
-        </ScrollView>
+        </>
     );
 }
 

From ceec9bb1c214becdcfc9ac739c5591218ebe5fb5 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 2 Aug 2023 17:00:26 -0700
Subject: [PATCH 15/39] Fade the last half waypoint shown in the list

---
 package-lock.json                             | 31 +++++++++++++++++++
 package.json                                  |  2 ++
 src/components/DistanceRequest.js             |  8 ++++-
 src/components/LinearGradient/index.js        |  3 ++
 src/components/LinearGradient/index.native.js |  3 ++
 5 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 src/components/LinearGradient/index.js
 create mode 100644 src/components/LinearGradient/index.native.js

diff --git a/package-lock.json b/package-lock.json
index 43116c18eed4..59f3b8099357 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -75,6 +75,7 @@
         "react-native-image-picker": "^5.1.0",
         "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#8393b7e58df6ff65fd41f60aee8ece8822c91e2b",
         "react-native-key-command": "^1.0.1",
+        "react-native-linear-gradient": "^2.8.1",
         "react-native-localize": "^2.2.6",
         "react-native-modal": "^13.0.0",
         "react-native-onyx": "1.0.52",
@@ -92,6 +93,7 @@
         "react-native-svg": "^13.9.0",
         "react-native-view-shot": "^3.6.0",
         "react-native-vision-camera": "^2.15.4",
+        "react-native-web-linear-gradient": "^1.1.2",
         "react-native-web-lottie": "^1.4.4",
         "react-native-webview": "^11.17.2",
         "react-pdf": "^6.2.2",
@@ -36752,6 +36754,15 @@
         "react-native-web": "^0.18.1"
       }
     },
+    "node_modules/react-native-linear-gradient": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.8.1.tgz",
+      "integrity": "sha512-934R4Bnjo7mYT38W9ypS1Dq/YW6TgyGdkHg+w72HNxN0ZDKG1GqAnZ6XlicMUYJDh7ViiJAKN8eOF3Ho0N4J0Q==",
+      "peerDependencies": {
+        "react": "*",
+        "react-native": "*"
+      }
+    },
     "node_modules/react-native-localize": {
       "version": "2.2.6",
       "resolved": "https://registry.npmjs.org/react-native-localize/-/react-native-localize-2.2.6.tgz",
@@ -37052,6 +37063,14 @@
         "react-dom": "^17.0.2 || ^18.0.0"
       }
     },
+    "node_modules/react-native-web-linear-gradient": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/react-native-web-linear-gradient/-/react-native-web-linear-gradient-1.1.2.tgz",
+      "integrity": "sha512-SmUnpwT49CEe78pXvIvYf72Es8Pv+ZYKCnEOgb2zAKpEUDMo0+xElfRJhwt5nfI8krJ5WbFPKnoDgD0uUjAN1A==",
+      "peerDependencies": {
+        "react-native-web": "*"
+      }
+    },
     "node_modules/react-native-web-lottie": {
       "version": "1.4.4",
       "resolved": "https://registry.npmjs.org/react-native-web-lottie/-/react-native-web-lottie-1.4.4.tgz",
@@ -68537,6 +68556,12 @@
         "underscore": "^1.13.4"
       }
     },
+    "react-native-linear-gradient": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.8.1.tgz",
+      "integrity": "sha512-934R4Bnjo7mYT38W9ypS1Dq/YW6TgyGdkHg+w72HNxN0ZDKG1GqAnZ6XlicMUYJDh7ViiJAKN8eOF3Ho0N4J0Q==",
+      "requires": {}
+    },
     "react-native-localize": {
       "version": "2.2.6",
       "resolved": "https://registry.npmjs.org/react-native-localize/-/react-native-localize-2.2.6.tgz",
@@ -68716,6 +68741,12 @@
         "styleq": "^0.1.2"
       }
     },
+    "react-native-web-linear-gradient": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/react-native-web-linear-gradient/-/react-native-web-linear-gradient-1.1.2.tgz",
+      "integrity": "sha512-SmUnpwT49CEe78pXvIvYf72Es8Pv+ZYKCnEOgb2zAKpEUDMo0+xElfRJhwt5nfI8krJ5WbFPKnoDgD0uUjAN1A==",
+      "requires": {}
+    },
     "react-native-web-lottie": {
       "version": "1.4.4",
       "resolved": "https://registry.npmjs.org/react-native-web-lottie/-/react-native-web-lottie-1.4.4.tgz",
diff --git a/package.json b/package.json
index 2fa7e3cddbbf..e447c199e3ae 100644
--- a/package.json
+++ b/package.json
@@ -113,6 +113,7 @@
     "react-native-image-picker": "^5.1.0",
     "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#8393b7e58df6ff65fd41f60aee8ece8822c91e2b",
     "react-native-key-command": "^1.0.1",
+    "react-native-linear-gradient": "^2.8.1",
     "react-native-localize": "^2.2.6",
     "react-native-modal": "^13.0.0",
     "react-native-onyx": "1.0.52",
@@ -130,6 +131,7 @@
     "react-native-svg": "^13.9.0",
     "react-native-view-shot": "^3.6.0",
     "react-native-vision-camera": "^2.15.4",
+    "react-native-web-linear-gradient": "^1.1.2",
     "react-native-web-lottie": "^1.4.4",
     "react-native-webview": "^11.17.2",
     "react-pdf": "^6.2.2",
diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 4f97c212eb98..5d57becd04ac 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -13,6 +13,7 @@ import * as Expensicons from './Icon/Expensicons';
 import theme from '../styles/themes/default';
 import Button from './Button';
 import styles from '../styles/styles';
+import LinearGradient from './LinearGradient';
 
 const propTypes = {
     /** The transactionID of this request */
@@ -62,7 +63,8 @@ function DistanceRequest({transactionID, transaction, translate}) {
     };
 
     // Show 4 waypoints plus 1/2 of one
-    const scrollContainerHeight = menuItemHeight * 4 + Math.floor(menuItemHeight / 2);
+    const halfMenuItemHeight = Math.floor(menuItemHeight / 2);
+    const scrollContainerHeight = menuItemHeight * 4 + halfMenuItemHeight;
     return (
         <>
             <View style={{height: scrollContainerHeight}}>
@@ -95,6 +97,10 @@ function DistanceRequest({transactionID, transaction, translate}) {
                         );
                     })}
                 </ScrollView>
+                <LinearGradient
+                    style={[styles.pAbsolute, styles.b0, styles.l0, styles.r0, {height: halfMenuItemHeight}]}
+                    colors={[theme.transparent, theme.shadow]}
+                />
             </View>
             <View style={[styles.flexRow, styles.justifyContentCenter, styles.pt1]}>
                 <Button
diff --git a/src/components/LinearGradient/index.js b/src/components/LinearGradient/index.js
new file mode 100644
index 000000000000..8270681641d0
--- /dev/null
+++ b/src/components/LinearGradient/index.js
@@ -0,0 +1,3 @@
+import LinearGradient from 'react-native-web-linear-gradient';
+
+export default LinearGradient;
diff --git a/src/components/LinearGradient/index.native.js b/src/components/LinearGradient/index.native.js
new file mode 100644
index 000000000000..c8d5af2646b2
--- /dev/null
+++ b/src/components/LinearGradient/index.native.js
@@ -0,0 +1,3 @@
+import LinearGradient from 'react-native-linear-gradient';
+
+export default LinearGradient;

From 3509242105b26891418d2f55e9f81d1ff732542a Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 2 Aug 2023 17:01:28 -0700
Subject: [PATCH 16/39] Use key in list to fix console error

---
 src/components/DistanceRequest.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 5d57becd04ac..ad85145bab0f 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -85,6 +85,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
                             <View
                                 onLayout={index === 0 ? measureMenuItemHeight : null}
                                 ref={index === 0 ? firstMenuItem : null}
+                                key={key}
                             >
                                 <MenuItemWithTopDescription
                                     description={translate(descriptionKey)}

From bfa14b8e425a9f879f1180c679df7fd22b2a16c5 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 2 Aug 2023 17:17:11 -0700
Subject: [PATCH 17/39] Disable add stop at max of 25

---
 src/components/DistanceRequest.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index ad85145bab0f..89a5d2ff517e 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -15,6 +15,7 @@ import Button from './Button';
 import styles from '../styles/styles';
 import LinearGradient from './LinearGradient';
 
+const MAX_WAYPOINTS = 25;
 const propTypes = {
     /** The transactionID of this request */
     transactionID: PropTypes.string,
@@ -109,7 +110,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
                     icon={Expensicons.Plus}
                     onPress={() => Transaction.addStop(transactionID, lastWaypointIndex + 1)}
                     text={translate('distance.addStop')}
-                    isDisabled={false}
+                    isDisabled={_.size(waypoints) === MAX_WAYPOINTS}
                     innerStyles={[styles.ph10]}
                 />
             </View>

From 3232cc5fe34719a3e4df058adaa06b58491b90ba Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 2 Aug 2023 17:46:03 -0700
Subject: [PATCH 18/39] Only fade the waypoint when extending out of view

---
 src/components/DistanceRequest.js | 37 +++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 89a5d2ff517e..c895565625e1 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -16,6 +16,7 @@ import styles from '../styles/styles';
 import LinearGradient from './LinearGradient';
 
 const MAX_WAYPOINTS = 25;
+const MAX_WAYPOINTS_TO_DISPLAY = 4;
 const propTypes = {
     /** The transactionID of this request */
     transactionID: PropTypes.string,
@@ -41,6 +42,10 @@ const defaultProps = {
 };
 
 function DistanceRequest({transactionID, transaction, translate}) {
+    const [shouldShowGradient, setShouldShowGradient] = useState(false);
+    const [menuItemHeight, setMenuItemHeight] = useState(0);
+    const firstMenuItem = useRef(null);
+
     const waypoints = lodashGet(transaction, 'comment.waypoints', {});
     const lastWaypointIndex = _.size(waypoints) - 1;
 
@@ -52,8 +57,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
         Transaction.createInitialWaypoints(transaction.transactionID);
     }, [transaction.transactionID, waypoints]);
 
-    const firstMenuItem = useRef(null);
-    const [menuItemHeight, setMenuItemHeight] = useState(0);
+    // Measure the first waypoint to calculate how high the scroll view should be
     const measureMenuItemHeight = () => {
         if (!firstMenuItem.current) {
             return;
@@ -63,13 +67,26 @@ function DistanceRequest({transactionID, transaction, translate}) {
         });
     };
 
-    // Show 4 waypoints plus 1/2 of one
+    // Show the proper number of waypoints plus 1/2 of one
     const halfMenuItemHeight = Math.floor(menuItemHeight / 2);
-    const scrollContainerHeight = menuItemHeight * 4 + halfMenuItemHeight;
+    const scrollContainerHeight = menuItemHeight * MAX_WAYPOINTS_TO_DISPLAY + halfMenuItemHeight;
+
+    const updateGradientVisibility = (event = {}) => {
+        // If a waypoint extends past the bottom of the scroll container then show the gradient, else hide it.
+        const waypointEnd = _.size(waypoints) * menuItemHeight;
+        const visibleAreaEnd = lodashGet(event, 'nativeEvent.contentOffset.y', 0) + scrollContainerHeight;
+        setShouldShowGradient(waypointEnd > visibleAreaEnd);
+    };
+
+    useEffect(updateGradientVisibility, [waypoints, menuItemHeight, scrollContainerHeight]);
+
     return (
         <>
             <View style={{height: scrollContainerHeight}}>
-                <ScrollView>
+                <ScrollView
+                    onScroll={updateGradientVisibility}
+                    scrollEventThrottle={16}
+                >
                     {_.map(waypoints, (waypoint, key) => {
                         // key is of the form waypoint0, waypoint1, ...
                         const index = Number(key.replace('waypoint', ''));
@@ -99,10 +116,12 @@ function DistanceRequest({transactionID, transaction, translate}) {
                         );
                     })}
                 </ScrollView>
-                <LinearGradient
-                    style={[styles.pAbsolute, styles.b0, styles.l0, styles.r0, {height: halfMenuItemHeight}]}
-                    colors={[theme.transparent, theme.shadow]}
-                />
+                {shouldShowGradient && (
+                    <LinearGradient
+                        style={[styles.pAbsolute, styles.b0, styles.l0, styles.r0, {height: halfMenuItemHeight}]}
+                        colors={[theme.transparent, theme.shadow]}
+                    />
+                )}
             </View>
             <View style={[styles.flexRow, styles.justifyContentCenter, styles.pt1]}>
                 <Button

From 91ae1a09c806f46c162915f77e54041a559db50c Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 2 Aug 2023 17:56:32 -0700
Subject: [PATCH 19/39] Expand waypoint container until max size is hit

---
 src/components/DistanceRequest.js | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index c895565625e1..417eeaff5223 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -47,7 +47,8 @@ function DistanceRequest({transactionID, transaction, translate}) {
     const firstMenuItem = useRef(null);
 
     const waypoints = lodashGet(transaction, 'comment.waypoints', {});
-    const lastWaypointIndex = _.size(waypoints) - 1;
+    const numberOfWaypoints = _.size(waypoints);
+    const lastWaypointIndex = numberOfWaypoints - 1;
 
     useEffect(() => {
         if (!transaction.transactionID || !_.isEmpty(waypoints)) {
@@ -67,18 +68,23 @@ function DistanceRequest({transactionID, transaction, translate}) {
         });
     };
 
-    // Show the proper number of waypoints plus 1/2 of one
+    // The scroll container should be as small as possible and grow as waypoints are added
+    let scrollContainerHeight = menuItemHeight * numberOfWaypoints;
     const halfMenuItemHeight = Math.floor(menuItemHeight / 2);
-    const scrollContainerHeight = menuItemHeight * MAX_WAYPOINTS_TO_DISPLAY + halfMenuItemHeight;
+
+    // When there are more than we want to display, show the proper number of waypoints plus 1/2 of one to hint at scrolling
+    if (numberOfWaypoints > MAX_WAYPOINTS_TO_DISPLAY) {
+        scrollContainerHeight = menuItemHeight * MAX_WAYPOINTS_TO_DISPLAY + halfMenuItemHeight;
+    }
 
     const updateGradientVisibility = (event = {}) => {
         // If a waypoint extends past the bottom of the scroll container then show the gradient, else hide it.
-        const waypointEnd = _.size(waypoints) * menuItemHeight;
+        const waypointEnd = numberOfWaypoints * menuItemHeight;
         const visibleAreaEnd = lodashGet(event, 'nativeEvent.contentOffset.y', 0) + scrollContainerHeight;
         setShouldShowGradient(waypointEnd > visibleAreaEnd);
     };
 
-    useEffect(updateGradientVisibility, [waypoints, menuItemHeight, scrollContainerHeight]);
+    useEffect(updateGradientVisibility, [waypoints, numberOfWaypoints, menuItemHeight, scrollContainerHeight]);
 
     return (
         <>
@@ -129,7 +135,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
                     icon={Expensicons.Plus}
                     onPress={() => Transaction.addStop(transactionID, lastWaypointIndex + 1)}
                     text={translate('distance.addStop')}
-                    isDisabled={_.size(waypoints) === MAX_WAYPOINTS}
+                    isDisabled={numberOfWaypoints === MAX_WAYPOINTS}
                     innerStyles={[styles.ph10]}
                 />
             </View>

From aa755c85eb33b2e28c054a54ab7cace1254c7cf3 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 2 Aug 2023 18:15:26 -0700
Subject: [PATCH 20/39] Fade waypoints into background vs black

---
 src/components/DistanceRequest.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 417eeaff5223..9401d3abbc45 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -125,7 +125,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
                 {shouldShowGradient && (
                     <LinearGradient
                         style={[styles.pAbsolute, styles.b0, styles.l0, styles.r0, {height: halfMenuItemHeight}]}
-                        colors={[theme.transparent, theme.shadow]}
+                        colors={[theme.transparent, theme.modalBackground]}
                     />
                 )}
             </View>

From c1f02bf9a9b58968024a620c459f608be807a3ba Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 4 Aug 2023 11:03:12 -0700
Subject: [PATCH 21/39] Add distance icons

---
 assets/images/drag-handles.svg     |  7 +++++++
 assets/images/location.svg         | 10 ++++++++++
 src/components/Icon/Expensicons.js |  4 ++++
 3 files changed, 21 insertions(+)
 create mode 100644 assets/images/drag-handles.svg
 create mode 100644 assets/images/location.svg

diff --git a/assets/images/drag-handles.svg b/assets/images/drag-handles.svg
new file mode 100644
index 000000000000..ec4fc4ccc672
--- /dev/null
+++ b/assets/images/drag-handles.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 27.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
+<path d="M1,6c0-1.1,0.9-2,2-2h14c1.1,0,2,0.9,2,2s-0.9,2-2,2H3C1.9,8,1,7.1,1,6z"/>
+<path d="M1,14c0-1.1,0.9-2,2-2h14c1.1,0,2,0.9,2,2s-0.9,2-2,2H3C1.9,16,1,15.1,1,14z"/>
+</svg>
diff --git a/assets/images/location.svg b/assets/images/location.svg
new file mode 100644
index 000000000000..ad8102051e26
--- /dev/null
+++ b/assets/images/location.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 27.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill-rule:evenodd;clip-rule:evenodd;}
+</style>
+<path class="st0" d="M10,18c0,0,7-5,7-10.2C17,4,13.9,1,10,1C6.1,1,3,4,3,7.8C3,13,10,18,10,18z M10,8c1.1,0,2-0.9,2-2s-0.9-2-2-2
+	C8.9,4,8,4.9,8,6S8.9,8,10,8z"/>
+</svg>
diff --git a/src/components/Icon/Expensicons.js b/src/components/Icon/Expensicons.js
index b0c1d5a9249c..637ab0aff1dd 100644
--- a/src/components/Icon/Expensicons.js
+++ b/src/components/Icon/Expensicons.js
@@ -34,6 +34,7 @@ import DomainRoomAvatar from '../../../assets/images/avatars/domain-room.svg';
 import DotIndicator from '../../../assets/images/dot-indicator.svg';
 import DownArrow from '../../../assets/images/down.svg';
 import Download from '../../../assets/images/download.svg';
+import DragHandles from '../../../assets/images/drag-handles.svg';
 import Emoji from '../../../assets/images/emoji.svg';
 import Exclamation from '../../../assets/images/exclamation.svg';
 import Exit from '../../../assets/images/exit.svg';
@@ -60,6 +61,7 @@ import Key from '../../../assets/images/key.svg';
 import Keyboard from '../../../assets/images/keyboard.svg';
 import Link from '../../../assets/images/link.svg';
 import LinkCopy from '../../../assets/images/link-copy.svg';
+import Location from '../../../assets/images/location.svg';
 import Lock from '../../../assets/images/lock.svg';
 import LoungeAccess from '../../../assets/images/lounge-access.svg';
 import Luggage from '../../../assets/images/luggage.svg';
@@ -157,6 +159,7 @@ export {
     DownArrow,
     Download,
     DragAndDrop,
+    DragHandles,
     Emoji,
     Exclamation,
     Exit,
@@ -187,6 +190,7 @@ export {
     Keyboard,
     Link,
     LinkCopy,
+    Location,
     Lock,
     LoungeAccess,
     Luggage,

From 77f3f35512a57120efa72fe29d407754e05df598 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 4 Aug 2023 11:03:39 -0700
Subject: [PATCH 22/39] WIP set waypoint icon based on index

---
 src/components/DistanceRequest.js | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 9401d3abbc45..966186e25052 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -97,12 +97,20 @@ function DistanceRequest({transactionID, transaction, translate}) {
                         // key is of the form waypoint0, waypoint1, ...
                         const index = Number(key.replace('waypoint', ''));
                         let descriptionKey = 'distance.waypointDescription.';
+                        let waypointIcon;
+                        let waypointIconFill;
                         if (index === 0) {
                             descriptionKey += 'start';
+                            waypointIcon = Expensicons.DotIndicator
+                            waypointIconFill = theme.text;
                         } else if (index === lastWaypointIndex) {
                             descriptionKey += 'finish';
+                            waypointIcon = Expensicons.Location;
+                            waypointIconFill = theme.icon;
                         } else {
                             descriptionKey += 'stop';
+                            waypointIcon = Expensicons.DotIndicator;
+                            waypointIconFill = theme.icon;
                         }
 
                         return (
@@ -113,9 +121,9 @@ function DistanceRequest({transactionID, transaction, translate}) {
                             >
                                 <MenuItemWithTopDescription
                                     description={translate(descriptionKey)}
-                                    icon={Expensicons.Menu}
-                                    secondaryIcon={Expensicons.DotIndicator}
-                                    secondaryIconFill={theme.icon}
+                                    icon={Expensicons.DragHandles}
+                                    secondaryIcon={waypointIcon}
+                                    secondaryIconFill={waypointIconFill}
                                     shouldShowRightIcon
                                 />
                             </View>

From 5c517e6b66c551cea67440a3460b97a476d3c003 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 4 Aug 2023 11:19:21 -0700
Subject: [PATCH 23/39] Same default color for all waypoint icons

---
 src/components/DistanceRequest.js | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 966186e25052..bcc55caced69 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -98,19 +98,15 @@ function DistanceRequest({transactionID, transaction, translate}) {
                         const index = Number(key.replace('waypoint', ''));
                         let descriptionKey = 'distance.waypointDescription.';
                         let waypointIcon;
-                        let waypointIconFill;
                         if (index === 0) {
                             descriptionKey += 'start';
                             waypointIcon = Expensicons.DotIndicator
-                            waypointIconFill = theme.text;
                         } else if (index === lastWaypointIndex) {
                             descriptionKey += 'finish';
                             waypointIcon = Expensicons.Location;
-                            waypointIconFill = theme.icon;
                         } else {
                             descriptionKey += 'stop';
                             waypointIcon = Expensicons.DotIndicator;
-                            waypointIconFill = theme.icon;
                         }
 
                         return (
@@ -123,7 +119,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
                                     description={translate(descriptionKey)}
                                     icon={Expensicons.DragHandles}
                                     secondaryIcon={waypointIcon}
-                                    secondaryIconFill={waypointIconFill}
+                                    secondaryIconFill={theme.icon}
                                     shouldShowRightIcon
                                 />
                             </View>

From 792aab198f03153e6daf8fb93e4039b45ddc9f47 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 4 Aug 2023 12:54:59 -0700
Subject: [PATCH 24/39] WIP scroll fade with dynamic waypoints sizes

---
 src/components/DistanceRequest.js | 52 +++++++++++++++++--------------
 src/styles/styles.js              |  2 ++
 2 files changed, 31 insertions(+), 23 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index bcc55caced69..fa18d9be3982 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -17,6 +17,7 @@ import LinearGradient from './LinearGradient';
 
 const MAX_WAYPOINTS = 25;
 const MAX_WAYPOINTS_TO_DISPLAY = 4;
+
 const propTypes = {
     /** The transactionID of this request */
     transactionID: PropTypes.string,
@@ -43,13 +44,19 @@ const defaultProps = {
 
 function DistanceRequest({transactionID, transaction, translate}) {
     const [shouldShowGradient, setShouldShowGradient] = useState(false);
-    const [menuItemHeight, setMenuItemHeight] = useState(0);
-    const firstMenuItem = useRef(null);
+    const [scrollContainerHeight, setScrollContainerHeight] = useState(0);
+    const scrollContainer = useRef(null);
 
     const waypoints = lodashGet(transaction, 'comment.waypoints', {});
     const numberOfWaypoints = _.size(waypoints);
     const lastWaypointIndex = numberOfWaypoints - 1;
 
+    // Show up to the max number of waypoints plus 1/2 of one to hint at scrolling
+    const halfMenuItemHeight = Math.floor(styles.baseMenuItemHeight / 2);
+    const maxWaypointsHeight = styles.baseMenuItemHeight * MAX_WAYPOINTS_TO_DISPLAY;
+    const scrollContainerMaxHeight = maxWaypointsHeight + halfMenuItemHeight;
+    console.log('scrollContainerMaxHeight', scrollContainerMaxHeight);
+
     useEffect(() => {
         if (!transaction.transactionID || !_.isEmpty(waypoints)) {
             return;
@@ -58,37 +65,38 @@ function DistanceRequest({transactionID, transaction, translate}) {
         Transaction.createInitialWaypoints(transaction.transactionID);
     }, [transaction.transactionID, waypoints]);
 
-    // Measure the first waypoint to calculate how high the scroll view should be
-    const measureMenuItemHeight = () => {
-        if (!firstMenuItem.current) {
+    // Measure the scroll container height and decide if we need to fade a waypoint
+    const measureScrollContainerHeight = () => {
+        console.log('measureScrollContainerHeight, scrollContainer=', scrollContainer);
+        if (!scrollContainer.current) {
             return;
         }
-        firstMenuItem.current.measure((x, y, width, height) => {
-            setMenuItemHeight(height);
+        scrollContainer.current.measure((x, y, width, height) => {
+            console.log('measure height', height);
+            setScrollContainerHeight(height);
         });
     };
-
-    // The scroll container should be as small as possible and grow as waypoints are added
-    let scrollContainerHeight = menuItemHeight * numberOfWaypoints;
-    const halfMenuItemHeight = Math.floor(menuItemHeight / 2);
-
-    // When there are more than we want to display, show the proper number of waypoints plus 1/2 of one to hint at scrolling
-    if (numberOfWaypoints > MAX_WAYPOINTS_TO_DISPLAY) {
-        scrollContainerHeight = menuItemHeight * MAX_WAYPOINTS_TO_DISPLAY + halfMenuItemHeight;
-    }
+    useEffect(measureScrollContainerHeight, [scrollContainer])
 
     const updateGradientVisibility = (event = {}) => {
-        // If a waypoint extends past the bottom of the scroll container then show the gradient, else hide it.
-        const waypointEnd = numberOfWaypoints * menuItemHeight;
+        // If a waypoint extends past the bottom of the visible area show the gradient, else hide it.
         const visibleAreaEnd = lodashGet(event, 'nativeEvent.contentOffset.y', 0) + scrollContainerHeight;
-        setShouldShowGradient(waypointEnd > visibleAreaEnd);
+        const contentSize = lodashGet(event, 'nativeEvent.contentSize.height', 0);
+        console.log('scrollContainerHeight', scrollContainerHeight);
+        console.log('contentSize', contentSize);
+        console.log('visibleAreaEnd', visibleAreaEnd);
+        setShouldShowGradient(visibleAreaEnd < contentSize);
     };
 
-    useEffect(updateGradientVisibility, [waypoints, numberOfWaypoints, menuItemHeight, scrollContainerHeight]);
+    useEffect(updateGradientVisibility, [scrollContainerHeight]);
 
     return (
         <>
-            <View style={{height: scrollContainerHeight}}>
+            <View
+                style={{maxHeight: scrollContainerMaxHeight}}
+                onLayout={measureScrollContainerHeight}
+                ref={scrollContainer}
+            >
                 <ScrollView
                     onScroll={updateGradientVisibility}
                     scrollEventThrottle={16}
@@ -111,8 +119,6 @@ function DistanceRequest({transactionID, transaction, translate}) {
 
                         return (
                             <View
-                                onLayout={index === 0 ? measureMenuItemHeight : null}
-                                ref={index === 0 ? firstMenuItem : null}
                                 key={key}
                             >
                                 <MenuItemWithTopDescription
diff --git a/src/styles/styles.js b/src/styles/styles.js
index ae4f55c14da2..bd691e7d6541 100644
--- a/src/styles/styles.js
+++ b/src/styles/styles.js
@@ -1405,6 +1405,8 @@ const styles = {
         minHeight: variables.componentSizeNormal,
     },
 
+    baseMenuItemHeight: 64,
+
     chatLinkRowPressable: {
         minWidth: 0,
         textDecorationLine: 'none',

From c973198fe459d31c9e1e04c84ae95f98515d030f Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 4 Aug 2023 13:10:06 -0700
Subject: [PATCH 25/39] Get scroll content height using it's callback

---
 src/components/DistanceRequest.js | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index fa18d9be3982..7288332706e1 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -45,6 +45,7 @@ const defaultProps = {
 function DistanceRequest({transactionID, transaction, translate}) {
     const [shouldShowGradient, setShouldShowGradient] = useState(false);
     const [scrollContainerHeight, setScrollContainerHeight] = useState(0);
+    const [scrollContentHeight, setScrollContentHeight] = useState(0);
     const scrollContainer = useRef(null);
 
     const waypoints = lodashGet(transaction, 'comment.waypoints', {});
@@ -81,14 +82,12 @@ function DistanceRequest({transactionID, transaction, translate}) {
     const updateGradientVisibility = (event = {}) => {
         // If a waypoint extends past the bottom of the visible area show the gradient, else hide it.
         const visibleAreaEnd = lodashGet(event, 'nativeEvent.contentOffset.y', 0) + scrollContainerHeight;
-        const contentSize = lodashGet(event, 'nativeEvent.contentSize.height', 0);
         console.log('scrollContainerHeight', scrollContainerHeight);
-        console.log('contentSize', contentSize);
         console.log('visibleAreaEnd', visibleAreaEnd);
-        setShouldShowGradient(visibleAreaEnd < contentSize);
+        setShouldShowGradient(visibleAreaEnd < scrollContentHeight);
     };
 
-    useEffect(updateGradientVisibility, [scrollContainerHeight]);
+    useEffect(updateGradientVisibility, [scrollContainerHeight, scrollContentHeight]);
 
     return (
         <>
@@ -98,6 +97,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
                 ref={scrollContainer}
             >
                 <ScrollView
+                    onContentSizeChange={(width, height) => setScrollContentHeight(height)}
                     onScroll={updateGradientVisibility}
                     scrollEventThrottle={16}
                 >

From 1e97449c7b9027e286a4cdb0eee3057c53ba1547 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 4 Aug 2023 13:12:01 -0700
Subject: [PATCH 26/39] Remove console logs

---
 src/components/DistanceRequest.js | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 7288332706e1..33d4ea95b9f7 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -56,7 +56,6 @@ function DistanceRequest({transactionID, transaction, translate}) {
     const halfMenuItemHeight = Math.floor(styles.baseMenuItemHeight / 2);
     const maxWaypointsHeight = styles.baseMenuItemHeight * MAX_WAYPOINTS_TO_DISPLAY;
     const scrollContainerMaxHeight = maxWaypointsHeight + halfMenuItemHeight;
-    console.log('scrollContainerMaxHeight', scrollContainerMaxHeight);
 
     useEffect(() => {
         if (!transaction.transactionID || !_.isEmpty(waypoints)) {
@@ -68,12 +67,10 @@ function DistanceRequest({transactionID, transaction, translate}) {
 
     // Measure the scroll container height and decide if we need to fade a waypoint
     const measureScrollContainerHeight = () => {
-        console.log('measureScrollContainerHeight, scrollContainer=', scrollContainer);
         if (!scrollContainer.current) {
             return;
         }
         scrollContainer.current.measure((x, y, width, height) => {
-            console.log('measure height', height);
             setScrollContainerHeight(height);
         });
     };
@@ -82,8 +79,6 @@ function DistanceRequest({transactionID, transaction, translate}) {
     const updateGradientVisibility = (event = {}) => {
         // If a waypoint extends past the bottom of the visible area show the gradient, else hide it.
         const visibleAreaEnd = lodashGet(event, 'nativeEvent.contentOffset.y', 0) + scrollContainerHeight;
-        console.log('scrollContainerHeight', scrollContainerHeight);
-        console.log('visibleAreaEnd', visibleAreaEnd);
         setShouldShowGradient(visibleAreaEnd < scrollContentHeight);
     };
 

From 7b6d485014b6d0210c98bb05d97402437e1728ae Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 4 Aug 2023 13:22:45 -0700
Subject: [PATCH 27/39] layout event to measure scroll container height

---
 src/components/DistanceRequest.js | 18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 33d4ea95b9f7..4257902db5c4 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -46,7 +46,6 @@ function DistanceRequest({transactionID, transaction, translate}) {
     const [shouldShowGradient, setShouldShowGradient] = useState(false);
     const [scrollContainerHeight, setScrollContainerHeight] = useState(0);
     const [scrollContentHeight, setScrollContentHeight] = useState(0);
-    const scrollContainer = useRef(null);
 
     const waypoints = lodashGet(transaction, 'comment.waypoints', {});
     const numberOfWaypoints = _.size(waypoints);
@@ -54,8 +53,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
 
     // Show up to the max number of waypoints plus 1/2 of one to hint at scrolling
     const halfMenuItemHeight = Math.floor(styles.baseMenuItemHeight / 2);
-    const maxWaypointsHeight = styles.baseMenuItemHeight * MAX_WAYPOINTS_TO_DISPLAY;
-    const scrollContainerMaxHeight = maxWaypointsHeight + halfMenuItemHeight;
+    const scrollContainerMaxHeight = styles.baseMenuItemHeight * MAX_WAYPOINTS_TO_DISPLAY + halfMenuItemHeight;
 
     useEffect(() => {
         if (!transaction.transactionID || !_.isEmpty(waypoints)) {
@@ -65,17 +63,6 @@ function DistanceRequest({transactionID, transaction, translate}) {
         Transaction.createInitialWaypoints(transaction.transactionID);
     }, [transaction.transactionID, waypoints]);
 
-    // Measure the scroll container height and decide if we need to fade a waypoint
-    const measureScrollContainerHeight = () => {
-        if (!scrollContainer.current) {
-            return;
-        }
-        scrollContainer.current.measure((x, y, width, height) => {
-            setScrollContainerHeight(height);
-        });
-    };
-    useEffect(measureScrollContainerHeight, [scrollContainer])
-
     const updateGradientVisibility = (event = {}) => {
         // If a waypoint extends past the bottom of the visible area show the gradient, else hide it.
         const visibleAreaEnd = lodashGet(event, 'nativeEvent.contentOffset.y', 0) + scrollContainerHeight;
@@ -88,8 +75,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
         <>
             <View
                 style={{maxHeight: scrollContainerMaxHeight}}
-                onLayout={measureScrollContainerHeight}
-                ref={scrollContainer}
+                onLayout={(event = {}) => setScrollContainerHeight(lodashGet(event, 'nativeEvent.layout.height', 0))}
             >
                 <ScrollView
                     onContentSizeChange={(width, height) => setScrollContentHeight(height)}

From 6658bb8290d0911aa201689ac6d783ab83c83921 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 4 Aug 2023 13:25:35 -0700
Subject: [PATCH 28/39] More cleanup / style

---
 src/components/DistanceRequest.js | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 4257902db5c4..9937b98f060d 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -1,4 +1,4 @@
-import React, {useEffect, useRef, useState} from 'react';
+import React, {useEffect, useState} from 'react';
 import {ScrollView, View} from 'react-native';
 import lodashGet from 'lodash/get';
 import _ from 'underscore';
@@ -89,7 +89,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
                         let waypointIcon;
                         if (index === 0) {
                             descriptionKey += 'start';
-                            waypointIcon = Expensicons.DotIndicator
+                            waypointIcon = Expensicons.DotIndicator;
                         } else if (index === lastWaypointIndex) {
                             descriptionKey += 'finish';
                             waypointIcon = Expensicons.Location;
@@ -99,17 +99,14 @@ function DistanceRequest({transactionID, transaction, translate}) {
                         }
 
                         return (
-                            <View
+                            <MenuItemWithTopDescription
+                                description={translate(descriptionKey)}
+                                icon={Expensicons.DragHandles}
+                                secondaryIcon={waypointIcon}
+                                secondaryIconFill={theme.icon}
+                                shouldShowRightIcon
                                 key={key}
-                            >
-                                <MenuItemWithTopDescription
-                                    description={translate(descriptionKey)}
-                                    icon={Expensicons.DragHandles}
-                                    secondaryIcon={waypointIcon}
-                                    secondaryIconFill={theme.icon}
-                                    shouldShowRightIcon
-                                />
-                            </View>
+                            />
                         );
                     })}
                 </ScrollView>

From 9e9b0e5566f31332c9c26137ec17022418dc9b5d Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 4 Aug 2023 17:09:37 -0700
Subject: [PATCH 29/39] Add route for distance tab

---
 src/ROUTES.js                        | 1 +
 src/libs/Navigation/linkingConfig.js | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/src/ROUTES.js b/src/ROUTES.js
index a6e21baddf59..88db46a60113 100644
--- a/src/ROUTES.js
+++ b/src/ROUTES.js
@@ -87,6 +87,7 @@ export default {
     MONEY_REQUEST_DESCRIPTION: ':iouType/new/description/:reportID?',
     MONEY_REQUEST_MANUAL_TAB: ':iouType/new/:reportID?/manual',
     MONEY_REQUEST_SCAN_TAB: ':iouType/new/:reportID?/scan',
+    MONEY_REQUEST_DISTANCE_TAB: ':iouType/new/:reportID?/distance',
     IOU_SEND_ADD_BANK_ACCOUNT: `${IOU_SEND}/add-bank-account`,
     IOU_SEND_ADD_DEBIT_CARD: `${IOU_SEND}/add-debit-card`,
     IOU_SEND_ENABLE_PAYMENTS: `${IOU_SEND}/enable-payments`,
diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js
index 04a72b15dd18..6c4d58a4c585 100644
--- a/src/libs/Navigation/linkingConfig.js
+++ b/src/libs/Navigation/linkingConfig.js
@@ -302,6 +302,10 @@ export default {
                                         path: ROUTES.MONEY_REQUEST_SCAN_TAB,
                                         exact: true,
                                     },
+                                    distance: {
+                                        path: ROUTES.MONEY_REQUEST_DISTANCE_TAB,
+                                        exact: true,
+                                    },
                                 },
                             },
                             Money_Request_Amount: ROUTES.MONEY_REQUEST_AMOUNT,

From dd12bcc34b778043a513ebf18e3907b65144cca5 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Fri, 4 Aug 2023 17:18:57 -0700
Subject: [PATCH 30/39] Add unchecked translations

---
 src/languages/es.js | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/languages/es.js b/src/languages/es.js
index e85ccdd5c510..8b134b6831df 100644
--- a/src/languages/es.js
+++ b/src/languages/es.js
@@ -2035,6 +2035,14 @@ export default {
         levelTwoResult: 'Mensaje ocultado del canal, más advertencia anónima y mensaje reportado para revisión.',
         levelThreeResult: 'Mensaje eliminado del canal, más advertencia anónima y mensaje reportado para revisión.',
     },
+    distance: {
+        addStop: 'Añadir parada',
+        waypointDescription: {
+            start: 'El comienzo',
+            finish: 'El final',
+            stop: 'La parada',
+        },
+    },
     countrySelectorModal: {
         placeholderText: 'Buscar para ver opciones',
     },

From 9b340565f37e33bd789ef856aa1c3861078eacfb Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Mon, 7 Aug 2023 14:28:38 -0700
Subject: [PATCH 31/39] Use unique unfilled dot for start waypoint

---
 assets/images/dot-indicator-unfilled.svg | 10 ++++++++++
 src/components/DistanceRequest.js        |  2 +-
 src/components/Icon/Expensicons.js       |  2 ++
 3 files changed, 13 insertions(+), 1 deletion(-)
 create mode 100644 assets/images/dot-indicator-unfilled.svg

diff --git a/assets/images/dot-indicator-unfilled.svg b/assets/images/dot-indicator-unfilled.svg
new file mode 100644
index 000000000000..ae131b1c2cba
--- /dev/null
+++ b/assets/images/dot-indicator-unfilled.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 27.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill-rule:evenodd;clip-rule:evenodd;}
+</style>
+<path class="st0" d="M10,15.5c3,0,5.5-2.5,5.5-5.5c0-3-2.5-5.5-5.5-5.5C7,4.5,4.5,7,4.5,10C4.5,13,7,15.5,10,15.5z M10,17.5
+	c4.1,0,7.5-3.4,7.5-7.5c0-4.1-3.4-7.5-7.5-7.5c-4.1,0-7.5,3.4-7.5,7.5C2.5,14.1,5.9,17.5,10,17.5z"/>
+</svg>
diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 9937b98f060d..767052f66b48 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -89,7 +89,7 @@ function DistanceRequest({transactionID, transaction, translate}) {
                         let waypointIcon;
                         if (index === 0) {
                             descriptionKey += 'start';
-                            waypointIcon = Expensicons.DotIndicator;
+                            waypointIcon = Expensicons.DotIndicatorUnfilled;
                         } else if (index === lastWaypointIndex) {
                             descriptionKey += 'finish';
                             waypointIcon = Expensicons.Location;
diff --git a/src/components/Icon/Expensicons.js b/src/components/Icon/Expensicons.js
index 637ab0aff1dd..2f04c0199587 100644
--- a/src/components/Icon/Expensicons.js
+++ b/src/components/Icon/Expensicons.js
@@ -32,6 +32,7 @@ import Document from '../../../assets/images/document.svg';
 import DeletedRoomAvatar from '../../../assets/images/avatars/deleted-room.svg';
 import DomainRoomAvatar from '../../../assets/images/avatars/domain-room.svg';
 import DotIndicator from '../../../assets/images/dot-indicator.svg';
+import DotIndicatorUnfilled from '../../../assets/images/dot-indicator-unfilled.svg';
 import DownArrow from '../../../assets/images/down.svg';
 import Download from '../../../assets/images/download.svg';
 import DragHandles from '../../../assets/images/drag-handles.svg';
@@ -156,6 +157,7 @@ export {
     Document,
     DomainRoomAvatar,
     DotIndicator,
+    DotIndicatorUnfilled,
     DownArrow,
     Download,
     DragAndDrop,

From a8210419288cd948bc4322e19b4a3f00f36d01b8 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Mon, 7 Aug 2023 14:59:53 -0700
Subject: [PATCH 32/39] Remove unused props

---
 src/pages/iou/DistanceRequestPage.js | 43 +---------------------------
 1 file changed, 1 insertion(+), 42 deletions(-)

diff --git a/src/pages/iou/DistanceRequestPage.js b/src/pages/iou/DistanceRequestPage.js
index 9284975d4a27..ce0ac213f487 100644
--- a/src/pages/iou/DistanceRequestPage.js
+++ b/src/pages/iou/DistanceRequestPage.js
@@ -4,61 +4,22 @@ import {withOnyx} from 'react-native-onyx';
 import * as IOU from '../../libs/actions/IOU';
 import ONYXKEYS from '../../ONYXKEYS';
 import DistanceRequest from '../../components/DistanceRequest';
-import CONST from '../../CONST';
 import reportPropTypes from '../reportPropTypes';
 
 const propTypes = {
     /** The transactionID of this request */
     transactionID: PropTypes.string,
 
-    /** Route params */
-    route: PropTypes.shape({
-        params: PropTypes.shape({
-            iouType: PropTypes.string,
-            reportID: PropTypes.string,
-        }),
-    }),
-
     /** The report on which the request is initiated on */
     report: reportPropTypes,
-
-    /** Holds data related to Money Request view state, rather than the underlying Money Request data. */
-    iou: PropTypes.shape({
-        id: PropTypes.string,
-        amount: PropTypes.number,
-        currency: PropTypes.string,
-        participants: PropTypes.arrayOf(
-            PropTypes.shape({
-                accountID: PropTypes.number,
-                login: PropTypes.string,
-                isPolicyExpenseChat: PropTypes.bool,
-                isOwnPolicyExpenseChat: PropTypes.bool,
-                selected: PropTypes.bool,
-            }),
-        ),
-        transactionID: PropTypes.string,
-    }),
 };
 
 const defaultProps = {
     transactionID: '',
-    route: {
-        params: {
-            iouType: '',
-            reportID: '',
-        },
-    },
     report: {},
-    iou: {
-        id: '',
-        amount: 0,
-        currency: CONST.CURRENCY.USD,
-        participants: [],
-        transactionID: '',
-    },
 };
 
-function DistanceRequestPage({route, report, iou, transactionID}) {
+function DistanceRequestPage({report, transactionID}) {
     useEffect(() => {
         if (transactionID) {
             return;
@@ -68,9 +29,7 @@ function DistanceRequestPage({route, report, iou, transactionID}) {
 
     return (
         <DistanceRequest
-            route={route}
             report={report}
-            iou={iou}
             transactionID={transactionID}
         />
     );

From 324a88192b00492d6c7356d24128235e0b2d00a8 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Mon, 7 Aug 2023 15:09:39 -0700
Subject: [PATCH 33/39] Describe the purpose of the DistanceRequestPage

---
 src/pages/iou/DistanceRequestPage.js | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/pages/iou/DistanceRequestPage.js b/src/pages/iou/DistanceRequestPage.js
index ce0ac213f487..706ddc43b018 100644
--- a/src/pages/iou/DistanceRequestPage.js
+++ b/src/pages/iou/DistanceRequestPage.js
@@ -19,6 +19,8 @@ const defaultProps = {
     report: {},
 };
 
+// This component is responsible for getting the transactionID from the IOU key, or creating the transaction if it doesn't exist yet, and then passing the transactionID.
+// You can't use Onyx props in the withOnyx mapping, so we need to set up and access the transactionID here, and then pass it down so that DistanceRequest can subscribe to the transaction.
 function DistanceRequestPage({report, transactionID}) {
     useEffect(() => {
         if (transactionID) {

From 80bd8764b8722b967182d5a9258e59baff735770 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Mon, 7 Aug 2023 15:44:43 -0700
Subject: [PATCH 34/39] Update podfile for LinearGradient

---
 ios/Podfile.lock | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 343828fc5595..14ee07367746 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -21,6 +21,8 @@ PODS:
     - Airship/MessageCenter (= 16.11.3)
     - Airship/PreferenceCenter (= 16.11.3)
   - boost (1.76.0)
+  - BVLinearGradient (2.8.1):
+    - React-Core
   - CocoaAsyncSocket (7.6.5)
   - DoubleConversion (1.1.6)
   - FBLazyVector (0.72.1)
@@ -792,6 +794,7 @@ PODS:
 
 DEPENDENCIES:
   - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
+  - BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
   - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
   - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
   - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
@@ -942,6 +945,8 @@ SPEC REPOS:
 EXTERNAL SOURCES:
   boost:
     :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec"
+  BVLinearGradient:
+    :path: "../node_modules/react-native-linear-gradient"
   DoubleConversion:
     :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
   FBLazyVector:
@@ -1114,6 +1119,7 @@ SPEC CHECKSUMS:
   Airship: c70eed50e429f97f5adb285423c7291fb7a032ae
   AirshipFrameworkProxy: 7bc4130c668c6c98e2d4c60fe4c9eb61a999be99
   boost: 57d2868c099736d80fcd648bf211b4431e51a558
+  BVLinearGradient: 421743791a59d259aec53f4c58793aad031da2ca
   CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
   DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
   FBLazyVector: 55cd4593d570bd9e5e227488d637ce6a9581ce51

From 5435f9b4307b00d612c78d88b65b86a249c5d4dd Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Mon, 7 Aug 2023 15:45:22 -0700
Subject: [PATCH 35/39] Prevent crash with null transaction

---
 src/components/DistanceRequest.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 767052f66b48..45b831f083f5 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -139,7 +139,7 @@ export default compose(
     withOnyx({
         transaction: {
             key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}`,
-            selector: (transaction) => ({transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}}),
+            selector: (transaction) => (transaction ? {transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}} : null),
         },
     }),
 )(DistanceRequest);

From 96b04da89eb92b55d1c5d39e63adc60cd82c7775 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Mon, 7 Aug 2023 17:07:39 -0700
Subject: [PATCH 36/39] Update with native speaker translations

---
 src/languages/es.js | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/languages/es.js b/src/languages/es.js
index 8b134b6831df..3882ed74c03e 100644
--- a/src/languages/es.js
+++ b/src/languages/es.js
@@ -2036,11 +2036,11 @@ export default {
         levelThreeResult: 'Mensaje eliminado del canal, más advertencia anónima y mensaje reportado para revisión.',
     },
     distance: {
-        addStop: 'Añadir parada',
+        addStop: 'Agregar parada',
         waypointDescription: {
-            start: 'El comienzo',
-            finish: 'El final',
-            stop: 'La parada',
+            start: 'Comienzo',
+            finish: 'Final',
+            stop: 'Parada',
         },
     },
     countrySelectorModal: {

From 7062ac09a0d6ba71f82fc42aa2da3074756e26f6 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Tue, 8 Aug 2023 16:48:46 -0700
Subject: [PATCH 37/39] Add request routes for deep linking

---
 .well-known/apple-app-site-association   | 4 ++++
 android/app/src/main/AndroidManifest.xml | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/.well-known/apple-app-site-association b/.well-known/apple-app-site-association
index 8318b394d778..b6ae3a4c7702 100644
--- a/.well-known/apple-app-site-association
+++ b/.well-known/apple-app-site-association
@@ -32,6 +32,10 @@
                         "/": "/iou/*",
                         "comment": "I Owe You reports"
                     },
+                    {
+                        "/": "/request/*",
+                        "comment": "Money request"
+                    },
                     {
                         "/": "/enable-payments/*",
                         "comment": "Payments setup"
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index b95d68c9c935..72d9fabdc051 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -60,6 +60,7 @@
                 <data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/v"/>
                 <data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/bank-account"/>
                 <data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/iou"/>
+                <data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/request"/>
                 <data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/enable-payments"/>
                 <data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/statements"/>
                 <data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/concierge"/>
@@ -72,6 +73,7 @@
                 <data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/v"/>
                 <data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/bank-account"/>
                 <data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/iou"/>
+                <data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/request"/>
                 <data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/enable-payments"/>
                 <data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/statements"/>
                 <data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/concierge"/>

From d01471340fe3a15d0670b0c1a503864baa4dfa53 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 9 Aug 2023 15:34:27 -0700
Subject: [PATCH 38/39] baseMenuItemHeight is a style variable

---
 src/components/DistanceRequest.js | 5 +++--
 src/styles/styles.js              | 2 --
 src/styles/variables.js           | 2 ++
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 45b831f083f5..81cd76e45a6b 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -13,6 +13,7 @@ import * as Expensicons from './Icon/Expensicons';
 import theme from '../styles/themes/default';
 import Button from './Button';
 import styles from '../styles/styles';
+import variables from '../styles/variables';
 import LinearGradient from './LinearGradient';
 
 const MAX_WAYPOINTS = 25;
@@ -52,8 +53,8 @@ function DistanceRequest({transactionID, transaction, translate}) {
     const lastWaypointIndex = numberOfWaypoints - 1;
 
     // Show up to the max number of waypoints plus 1/2 of one to hint at scrolling
-    const halfMenuItemHeight = Math.floor(styles.baseMenuItemHeight / 2);
-    const scrollContainerMaxHeight = styles.baseMenuItemHeight * MAX_WAYPOINTS_TO_DISPLAY + halfMenuItemHeight;
+    const halfMenuItemHeight = Math.floor(variables.baseMenuItemHeight / 2);
+    const scrollContainerMaxHeight = variables.baseMenuItemHeight * MAX_WAYPOINTS_TO_DISPLAY + halfMenuItemHeight;
 
     useEffect(() => {
         if (!transaction.transactionID || !_.isEmpty(waypoints)) {
diff --git a/src/styles/styles.js b/src/styles/styles.js
index 633adc788747..535d59bcd468 100644
--- a/src/styles/styles.js
+++ b/src/styles/styles.js
@@ -1405,8 +1405,6 @@ const styles = {
         minHeight: variables.componentSizeNormal,
     },
 
-    baseMenuItemHeight: 64,
-
     chatLinkRowPressable: {
         minWidth: 0,
         textDecorationLine: 'none',
diff --git a/src/styles/variables.js b/src/styles/variables.js
index a771aa95906e..af4d81c93c79 100644
--- a/src/styles/variables.js
+++ b/src/styles/variables.js
@@ -150,4 +150,6 @@ export default {
     hoverDimValue: 1,
     pressDimValue: 0.8,
     qrShareHorizontalPadding: 32,
+
+    baseMenuItemHeight: 64,
 };

From 58f6ab586c07b28ddcc779c98fdcf3dc51950c19 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 9 Aug 2023 15:42:12 -0700
Subject: [PATCH 39/39] Comment up the props for our style guide

---
 src/components/DistanceRequest.js | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index 81cd76e45a6b..f499042f8887 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -25,11 +25,20 @@ const propTypes = {
 
     /** The optimistic transaction for this request */
     transaction: PropTypes.shape({
+        /** The transactionID of this request */
         transactionID: PropTypes.string,
+
+        /** The comment object on the transaction */
         comment: PropTypes.shape({
+            /** The waypoints defining the distance request */
             waypoints: PropTypes.shape({
+                /** The latitude of the waypoint */
                 lat: PropTypes.number,
+
+                /** The longitude of the waypoint */
                 lng: PropTypes.number,
+
+                /** The address of the waypoint */
                 address: PropTypes.string,
             }),
         }),
