From f5cee4e0bf6640e99e5b98d9057a66a4f3be0101 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 14 Sep 2023 11:49:25 +0700 Subject: [PATCH 1/5] fix: parent thread disappears in LHN when deleting the thread first chat --- src/libs/ReportActionsUtils.js | 15 +++++++++++++++ src/libs/ReportUtils.js | 16 ++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 20337bd9802f..333bda83fb88 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -619,6 +619,20 @@ function getAllReportActions(reportID) { return lodashGet(allReportActions, reportID, []); } +/** + * + * @param {*} reportID + * @returns {Boolean} + */ + +function isChildReportHasComment(reportID) { + const reportActions = allReportActions[reportID]; + if (_.isEmpty(reportActions)) { + return false; + } + return _.some(reportActions, (reportAction) => (reportAction.childVisibleActionCount || 0) > 0); +} + export { getSortedReportActions, getLastVisibleAction, @@ -656,4 +670,5 @@ export { isSplitBillAction, isTaskAction, getAllReportActions, + isChildReportHasComment, }; diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 3b3f7b976ba6..8de2d262a411 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2773,6 +2773,17 @@ function canAccessReport(report, policies, betas, allReportActions) { return true; } +/** + * + * @param {Object} report + * @param {String} currentReportId + * @returns {Boolean} + */ +function shouldHideReport(report, currentReportId) { + const parentReport = getParentReport(getReport(currentReportId)); + return parentReport.reportID !== report.reportID && !ReportActionsUtils.isChildReportHasComment(report.reportID); +} + /** * Takes several pieces of data from Onyx and evaluates if a report should be shown in the option list (either when searching * for reports or the reports shown in the LHN). @@ -2824,7 +2835,7 @@ function shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, const isEmptyChat = !lastVisibleMessage.lastMessageText && !lastVisibleMessage.lastMessageTranslationKey; // Hide only chat threads that haven't been commented on (other threads are actionable) - if (isChatThread(report) && isEmptyChat) { + if (isChatThread(report) && shouldHideReport(report, currentReportId) && isEmptyChat) { return false; } @@ -2850,7 +2861,7 @@ function shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, } // Hide chats between two users that haven't been commented on from the LNH - if (excludeEmptyChats && isEmptyChat && isChatReport(report) && !isChatRoom(report) && !isPolicyExpenseChat(report)) { + if (excludeEmptyChats && isEmptyChat && isChatReport(report) && !isChatRoom(report) && !isPolicyExpenseChat(report) && shouldHideReport(report, currentReportId)) { return false; } @@ -3628,4 +3639,5 @@ export { getReportPreviewDisplayTransactions, getTransactionsWithReceipts, hasMissingSmartscanFields, + shouldHideReport, }; From 028c034fca46a53f026a60e4acc175839116f7e3 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Fri, 15 Sep 2023 09:36:22 +0700 Subject: [PATCH 2/5] fix: merge main --- .github/workflows/testBuild.yml | 2 +- .storybook/theme.js | 18 +- android/app/build.gradle | 4 +- config/electronBuilder.config.js | 28 +- ios/NewExpensify/Info.plist | 4 +- ios/NewExpensifyTests/Info.plist | 4 +- package-lock.json | 29 +- package.json | 4 +- src/ROUTES.ts | 2 + src/components/AddPlaidBankAccount.js | 22 +- src/components/ConfirmedRoute.js | 4 +- .../DeeplinkRedirectLoadingIndicator.js | 4 +- .../distanceMapViewPropTypes.js | 55 ++ .../DistanceMapView/index.android.js | 48 ++ src/components/DistanceMapView/index.js | 15 + src/components/DistanceRequest.js | 64 +- src/components/DotIndicatorMessage.js | 4 +- src/components/FormHelpMessage.js | 4 +- src/components/GrowlNotification/index.js | 8 +- src/components/LHNOptionsList/OptionRowLHN.js | 3 +- .../LHNOptionsList/OptionRowLHNData.js | 49 +- src/components/MapView/MapView.tsx | 5 +- src/components/MapView/MapViewTypes.ts | 2 + src/components/MentionSuggestions.js | 3 +- src/components/MenuItem.js | 3 +- .../MoneyRequestConfirmationList.js | 2 +- src/components/MoneyRequestHeader.js | 42 +- src/components/OptionsList/BaseOptionsList.js | 16 +- src/components/OptionsListSkeletonView.js | 4 +- src/components/PDFView/index.native.js | 1 + src/components/QRShare/index.js | 2 +- .../ReportActionItem/MoneyReportView.js | 3 +- .../ReportActionItem/MoneyRequestPreview.js | 3 +- .../ReportActionItem/ReportPreview.js | 3 +- .../SkeletonViewLines.js | 4 +- .../SelectionList/BaseSelectionList.js | 2 +- src/components/SelectionList/UserListItem.js | 40 +- .../ValidateCode/ExpiredValidateCodeModal.js | 4 +- .../ValidateCode/JustSignedInModal.js | 4 +- .../ValidateCode/ValidateCodeModal.js | 4 +- .../AppNavigator/ModalStackNavigators.js | 7 + src/libs/Navigation/linkingConfig.js | 1 + src/libs/PersonalDetailsUtils.js | 3 +- src/libs/ReportActionsUtils.js | 12 + src/libs/ReportUtils.js | 2 +- src/libs/actions/IOU.js | 63 +- .../{OnyxUpdates.js => OnyxUpdates.ts} | 66 +- src/libs/asyncOpenURL/{index.js => index.ts} | 7 +- .../{index.website.js => index.website.ts} | 17 +- src/libs/asyncOpenURL/types.ts | 3 + src/libs/searchCountryOptions.js | 26 - src/libs/searchCountryOptions.ts | 39 ++ src/pages/EditRequestPage.js | 4 +- src/pages/LogInWithShortLivedAuthTokenPage.js | 4 +- .../BankAccountPlaidStep.js | 1 + .../ReimbursementAccount/BankAccountStep.js | 6 +- src/pages/home/HeaderView.js | 4 +- src/pages/home/ReportScreen.js | 3 +- .../report/ContextMenu/ContextMenuActions.js | 18 +- src/pages/home/report/LinkPreviewer.js | 4 +- src/pages/home/report/ReportActionItem.js | 4 +- src/pages/home/sidebar/SidebarLinks.js | 2 +- .../FloatingActionButtonAndPopover.js | 5 - src/pages/iou/DistanceRequestPage.js | 1 + .../MoneyRequestParticipantsPage.js | 50 +- .../MoneyRequestParticipantsSelector.js | 2 +- src/pages/iou/steps/NewRequestAmountPage.js | 2 +- src/styles/StyleUtils.ts | 59 +- src/styles/ThemeStylesProvider.tsx | 25 +- src/styles/colors.js | 73 ++- .../getReportActionContextMenuStyles.ts | 2 + src/styles/getTooltipStyles.ts | 7 +- src/styles/styles.js | 609 +++++++++--------- src/styles/themes/default.js | 160 ++--- src/styles/themes/light.js | 94 +++ src/styles/useThemeStyles.ts | 2 + src/styles/utilities/spacing.ts | 4 + src/types/onyx/OnyxUpdatesFromServer.ts | 9 +- src/types/onyx/index.ts | 3 +- 79 files changed, 1160 insertions(+), 765 deletions(-) create mode 100644 src/components/DistanceMapView/distanceMapViewPropTypes.js create mode 100644 src/components/DistanceMapView/index.android.js create mode 100644 src/components/DistanceMapView/index.js rename src/libs/actions/{OnyxUpdates.js => OnyxUpdates.ts} (62%) rename src/libs/asyncOpenURL/{index.js => index.ts} (60%) rename src/libs/asyncOpenURL/{index.website.js => index.website.ts} (61%) create mode 100644 src/libs/asyncOpenURL/types.ts delete mode 100644 src/libs/searchCountryOptions.js create mode 100644 src/libs/searchCountryOptions.ts create mode 100644 src/styles/themes/light.js diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index 6ded44d7059f..755ab6dbaa60 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -354,6 +354,6 @@ jobs: IOS: ${{ needs.iOS.result }} WEB: ${{ needs.web.result }} ANDROID_LINK: ${{steps.get_android_path.outputs.android_path}} - DESKTOP_LINK: https://ad-hoc-expensify-cash.s3.amazonaws.com/desktop/${{ env.PULL_REQUEST_NUMBER }}/NewExpensify.dmg + DESKTOP_LINK: https://ad-hoc-expensify-cash.s3.amazonaws.com/desktop/${{ env.PULL_REQUEST_NUMBER }}/NewExpensifyAdHoc.dmg IOS_LINK: ${{steps.get_ios_path.outputs.ios_path}} WEB_LINK: https://${{ env.PULL_REQUEST_NUMBER }}.pr-testing.expensify.com diff --git a/.storybook/theme.js b/.storybook/theme.js index 0867f6a830b5..96631764726f 100644 --- a/.storybook/theme.js +++ b/.storybook/theme.js @@ -7,17 +7,17 @@ export default create({ fontBase: 'ExpensifyNeue-Regular', fontCode: 'monospace', base: 'dark', - appBg: colors.greenHighlightBackground, - colorPrimary: colors.greenDefaultButton, + appBg: colors.darkHighlightBackground, + colorPrimary: colors.darkDefaultButton, colorSecondary: colors.green, - appContentBg: colors.greenAppBackground, - textColor: colors.white, - barTextColor: colors.white, + appContentBg: colors.darkAppBackground, + textColor: colors.darkPrimaryText, + barTextColor: colors.darkPrimaryText, barSelectedColor: colors.green, - barBg: colors.greenAppBackground, - appBorderColor: colors.greenBorders, - inputBg: colors.greenHighlightBackground, - inputBorder: colors.greenBorders, + barBg: colors.darkAppBackground, + appBorderColor: colors.darkBorders, + inputBg: colors.darkHighlightBackground, + inputBorder: colors.darkBorders, appBorderRadius: 8, inputBorderRadius: 8, }); diff --git a/android/app/build.gradle b/android/app/build.gradle index 62c95d20e3ca..1867a8cf85d2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -90,8 +90,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001036901 - versionName "1.3.69-1" + versionCode 1001037002 + versionName "1.3.70-2" } flavorDimensions "default" diff --git a/config/electronBuilder.config.js b/config/electronBuilder.config.js index da87c93ee367..a5478dbd8f78 100644 --- a/config/electronBuilder.config.js +++ b/config/electronBuilder.config.js @@ -21,6 +21,24 @@ const macIcon = { adhoc: './desktop/icon-adhoc.png', }; +const appIds = { + production: 'com.expensifyreactnative.chat', + staging: 'com.expensifyreactnative.dev.chat', + adhoc: 'com.expensifyreactnative.adhoc.chat', +}; + +const productNames = { + production: 'New Expensify', + staging: 'New Expensify Dev', + adhoc: 'New Expensify AdHoc', +}; + +const artifactNames = { + production: 'NewExpensify.dmg', + staging: 'NewExpensifyDev.dmg', + adhoc: 'NewExpensifyAdHoc.dmg', +}; + const isCorrectElectronEnv = ['production', 'staging', 'adhoc'].includes(process.env.ELECTRON_ENV); if (!isCorrectElectronEnv) { @@ -32,8 +50,8 @@ if (!isCorrectElectronEnv) { * It can be used to create local builds of the same, by omitting the `--publish` flag */ module.exports = { - appId: 'com.expensifyreactnative.chat', - productName: 'New Expensify', + appId: appIds[process.env.ELECTRON_ENV], + productName: productNames[process.env.ELECTRON_ENV], extraMetadata: { version, }, @@ -46,8 +64,8 @@ module.exports = { type: 'distribution', }, dmg: { - title: 'New Expensify', - artifactName: 'NewExpensify.dmg', + title: productNames[process.env.ELECTRON_ENV], + artifactName: artifactNames[process.env.ELECTRON_ENV], internetEnabled: true, }, publish: [ @@ -65,7 +83,7 @@ module.exports = { output: 'desktop-build', }, protocols: { - name: 'New Expensify', + name: productNames[process.env.ELECTRON_ENV], schemes: ['new-expensify'], }, }; diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index c9ba137b13de..9e4501eddea5 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.3.69 + 1.3.70 CFBundleSignature ???? CFBundleURLTypes @@ -40,7 +40,7 @@ CFBundleVersion - 1.3.69.1 + 1.3.70.2 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index e802856c4dd5..fd93684a1da3 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.3.69 + 1.3.70 CFBundleSignature ???? CFBundleVersion - 1.3.69.1 + 1.3.70.2 diff --git a/package-lock.json b/package-lock.json index 169ef273b29b..0ba372b22745 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.3.69-1", + "version": "1.3.70-2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.3.69-1", + "version": "1.3.70-2", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -65,7 +65,7 @@ "patch-package": "^8.0.0", "process": "^0.11.10", "prop-types": "^15.7.2", - "pusher-js": "7.4.0", + "pusher-js": "8.3.0", "react": "18.2.0", "react-collapse": "^5.1.0", "react-content-loader": "^6.1.0", @@ -39745,10 +39745,10 @@ } }, "node_modules/pusher-js": { - "version": "7.4.0", - "license": "MIT", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-8.3.0.tgz", + "integrity": "sha512-6GohP06WlVeomAQQe9qWh1IDzd3+InluWt+ZUOcecVK1SEQkg6a8uYVsvxSJm7cbccfmHhE0jDkmhKIhue8vmA==", "dependencies": { - "@types/node": "^14.14.31", "tweetnacl": "^1.0.3" } }, @@ -39760,11 +39760,6 @@ "node": ">=4.2.4" } }, - "node_modules/pusher-js/node_modules/@types/node": { - "version": "14.18.56", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.56.tgz", - "integrity": "sha512-+k+57NVS9opgrEn5l9c0gvD1r6C+PtyhVE4BTnMMRwiEA8ZO8uFcs6Yy2sXIy0eC95ZurBtRSvhZiHXBysbl6w==" - }, "node_modules/qrcode": { "version": "1.5.3", "license": "MIT", @@ -75499,17 +75494,11 @@ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" }, "pusher-js": { - "version": "7.4.0", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-8.3.0.tgz", + "integrity": "sha512-6GohP06WlVeomAQQe9qWh1IDzd3+InluWt+ZUOcecVK1SEQkg6a8uYVsvxSJm7cbccfmHhE0jDkmhKIhue8vmA==", "requires": { - "@types/node": "^14.14.31", "tweetnacl": "^1.0.3" - }, - "dependencies": { - "@types/node": { - "version": "14.18.56", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.56.tgz", - "integrity": "sha512-+k+57NVS9opgrEn5l9c0gvD1r6C+PtyhVE4BTnMMRwiEA8ZO8uFcs6Yy2sXIy0eC95ZurBtRSvhZiHXBysbl6w==" - } } }, "pusher-js-mock": { diff --git a/package.json b/package.json index 256ef013b0d7..97621503eb6f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.3.69-1", + "version": "1.3.70-2", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", @@ -107,7 +107,7 @@ "patch-package": "^8.0.0", "process": "^0.11.10", "prop-types": "^15.7.2", - "pusher-js": "7.4.0", + "pusher-js": "8.3.0", "react": "18.2.0", "react-collapse": "^5.1.0", "react-content-loader": "^6.1.0", diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 3bbdf4709cfc..a922eed04dea 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -104,6 +104,7 @@ export default { MONEY_REQUEST_SCAN_TAB: ':iouType/new/:reportID?/scan', MONEY_REQUEST_DISTANCE_TAB: ':iouType/new/:reportID?/distance', MONEY_REQUEST_WAYPOINT: ':iouType/new/waypoint/:waypointIndex', + MONEY_REQUEST_ADDRESS: ':iouType/new/address/:reportID?', 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`, @@ -118,6 +119,7 @@ export default { getMoneyRequestMerchantRoute: (iouType: string, reportID = '') => `${iouType}/new/merchant/${reportID}`, getMoneyRequestDistanceTabRoute: (iouType: string, reportID = '') => `${iouType}/new/${reportID}/distance`, getMoneyRequestWaypointRoute: (iouType: string, waypointIndex: number) => `${iouType}/new/waypoint/${waypointIndex}`, + getMoneyRequestAddressRoute: (iouType: string, reportID = '') => `${iouType}/new/address/${reportID}`, getMoneyRequestTagRoute: (iouType: string, reportID = '') => `${iouType}/new/tag/${reportID}`, SPLIT_BILL_DETAILS: `r/:reportID/split/:reportActionID`, getSplitBillDetailsRoute: (reportID: string, reportActionID: string) => `r/${reportID}/split/${reportActionID}`, diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index dbe7e46ff6aa..e2843ba7fae8 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -1,6 +1,7 @@ import _ from 'underscore'; -import React, {useEffect, useRef, useCallback} from 'react'; +import React, {useEffect, useRef, useCallback, useMemo} from 'react'; import {ActivityIndicator, View} from 'react-native'; +import {useIsFocused} from '@react-navigation/native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import lodashGet from 'lodash/get'; @@ -38,6 +39,9 @@ const propTypes = { /** Fired when the user exits the Plaid flow */ onExitPlaid: PropTypes.func, + /** Fired when the screen is blurred */ + onBlurPlaid: PropTypes.func, + /** Fired when the user selects an account */ onSelect: PropTypes.func, @@ -61,6 +65,7 @@ const defaultProps = { selectedPlaidAccountID: '', plaidLinkToken: '', onExitPlaid: () => {}, + onBlurPlaid: () => {}, onSelect: () => {}, text: '', receivedRedirectURI: null, @@ -75,6 +80,7 @@ function AddPlaidBankAccount({ selectedPlaidAccountID, plaidLinkToken, onExitPlaid, + onBlurPlaid, onSelect, text, receivedRedirectURI, @@ -88,6 +94,7 @@ function AddPlaidBankAccount({ const {translate} = useLocalize(); const {isOffline} = useNetwork(); + const isFocused = useIsFocused(); /** * @returns {String} @@ -102,6 +109,11 @@ function AddPlaidBankAccount({ } }; + /** + * @returns {Array} + */ + const plaidBankAccounts = useMemo(() => lodashGet(plaidData, 'bankAccounts') || [], [plaidData]); + /** * @returns {Boolean} * I'm using useCallback so the useEffect which uses this function doesn't run on every render. @@ -151,6 +163,13 @@ function AddPlaidBankAccount({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + useEffect(() => { + if (isFocused || plaidBankAccounts.length) { + return; + } + onBlurPlaid(); + }, [isFocused, onBlurPlaid, plaidBankAccounts.length]); + useEffect(() => { // If we are coming back from offline and we haven't authenticated with Plaid yet, we need to re-run our call to kick off Plaid // previousNetworkState.current also makes sure that this doesn't run on the first render. @@ -160,7 +179,6 @@ function AddPlaidBankAccount({ previousNetworkState.current = isOffline; }, [allowDebit, bankAccountID, isAuthenticatedWithPlaid, isOffline]); - const plaidBankAccounts = lodashGet(plaidData, 'bankAccounts') || []; const token = getPlaidLinkToken(); const options = _.map(plaidBankAccounts, (account) => ({ value: account.plaidAccountID, diff --git a/src/components/ConfirmedRoute.js b/src/components/ConfirmedRoute.js index 6790e8ae4d65..4bcdc4738a3c 100644 --- a/src/components/ConfirmedRoute.js +++ b/src/components/ConfirmedRoute.js @@ -16,7 +16,7 @@ import transactionPropTypes from './transactionPropTypes'; import BlockingView from './BlockingViews/BlockingView'; import useNetwork from '../hooks/useNetwork'; import useLocalize from '../hooks/useLocalize'; -import MapView from './MapView'; +import DistanceMapView from './DistanceMapView'; const propTypes = { /** Transaction that stores the distance request data */ @@ -90,7 +90,7 @@ function ConfirmedRoute({mapboxAccessToken, transaction}) { return ( <> {!isOffline && Boolean(mapboxAccessToken.token) ? ( - diff --git a/src/components/DistanceMapView/distanceMapViewPropTypes.js b/src/components/DistanceMapView/distanceMapViewPropTypes.js new file mode 100644 index 000000000000..05068cbc9b34 --- /dev/null +++ b/src/components/DistanceMapView/distanceMapViewPropTypes.js @@ -0,0 +1,55 @@ +import PropTypes from 'prop-types'; + +const propTypes = { + // Public access token to be used to fetch map data from Mapbox. + accessToken: PropTypes.string.isRequired, + + // Style applied to MapView component. Note some of the View Style props are not available on ViewMap + style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + + // Link to the style JSON document. + styleURL: PropTypes.string, + + // Whether map can tilt in the vertical direction. + pitchEnabled: PropTypes.bool, + + // Padding to apply when the map is adjusted to fit waypoints and directions + mapPadding: PropTypes.number, + + // Initial coordinate and zoom level + initialState: PropTypes.shape({ + location: PropTypes.arrayOf(PropTypes.number).isRequired, + zoom: PropTypes.number.isRequired, + }), + + // Locations on which to put markers + waypoints: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string, + coordinate: PropTypes.arrayOf(PropTypes.number), + markerComponent: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), + }), + ), + + // List of coordinates which together forms a direction. + directionCoordinates: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)), + + // Callback to call when the map is idle / ready + onMapReady: PropTypes.func, + + // Optional additional styles to be applied to the overlay + overlayStyle: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), +}; + +const defaultProps = { + styleURL: undefined, + pitchEnabled: false, + mapPadding: 0, + initialState: undefined, + waypoints: undefined, + directionCoordinates: undefined, + onMapReady: () => {}, + overlayStyle: undefined, +}; + +export {propTypes, defaultProps}; diff --git a/src/components/DistanceMapView/index.android.js b/src/components/DistanceMapView/index.android.js new file mode 100644 index 000000000000..ea72fb4de299 --- /dev/null +++ b/src/components/DistanceMapView/index.android.js @@ -0,0 +1,48 @@ +import React, {useState} from 'react'; +import {View} from 'react-native'; +import _ from 'underscore'; +import BlockingView from '../BlockingViews/BlockingView'; +import MapView from '../MapView'; +import styles from '../../styles/styles'; +import useNetwork from '../../hooks/useNetwork'; +import useLocalize from '../../hooks/useLocalize'; +import * as Expensicons from '../Icon/Expensicons'; +import * as StyleUtils from '../../styles/StyleUtils'; +import * as distanceMapViewPropTypes from './distanceMapViewPropTypes'; + +function DistanceMapView(props) { + const [isMapReady, setIsMapReady] = useState(false); + const {isOffline} = useNetwork(); + const {translate} = useLocalize(); + + return ( + <> + { + if (isMapReady) { + return; + } + setIsMapReady(true); + }} + /> + {!isMapReady && ( + + + + )} + + ); +} + +DistanceMapView.propTypes = distanceMapViewPropTypes.propTypes; +DistanceMapView.defaultProps = distanceMapViewPropTypes.defaultProps; +DistanceMapView.displayName = 'DistanceMapView'; + +export default DistanceMapView; diff --git a/src/components/DistanceMapView/index.js b/src/components/DistanceMapView/index.js new file mode 100644 index 000000000000..24bdf99382d1 --- /dev/null +++ b/src/components/DistanceMapView/index.js @@ -0,0 +1,15 @@ +import React from 'react'; +import _ from 'underscore'; +import MapView from '../MapView'; +import * as distanceMapViewPropTypes from './distanceMapViewPropTypes'; + +function DistanceMapView(props) { + // eslint-disable-next-line react/jsx-props-no-spreading + return ; +} + +DistanceMapView.propTypes = distanceMapViewPropTypes.propTypes; +DistanceMapView.defaultProps = distanceMapViewPropTypes.defaultProps; +DistanceMapView.displayName = 'DistanceMapView'; + +export default DistanceMapView; diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js index 9de98f365475..bf5a4cb9548b 100644 --- a/src/components/DistanceRequest.js +++ b/src/components/DistanceRequest.js @@ -26,9 +26,10 @@ import Navigation from '../libs/Navigation/Navigation'; import * as MapboxToken from '../libs/actions/MapboxToken'; import * as Transaction from '../libs/actions/Transaction'; import * as TransactionUtils from '../libs/TransactionUtils'; +import * as IOUUtils from '../libs/IOUUtils'; import Button from './Button'; -import MapView from './MapView'; +import DistanceMapView from './DistanceMapView'; import LinearGradient from './LinearGradient'; import * as Expensicons from './Icon/Expensicons'; import BlockingView from './BlockingViews/BlockingView'; @@ -38,6 +39,9 @@ import {iouPropTypes} from '../pages/iou/propTypes'; import reportPropTypes from '../pages/reportPropTypes'; import * as IOU from '../libs/actions/IOU'; import * as StyleUtils from '../styles/StyleUtils'; +import ScreenWrapper from './ScreenWrapper'; +import FullPageNotFoundView from './BlockingViews/FullPageNotFoundView'; +import HeaderWithBackButton from './HeaderWithBackButton'; const MAX_WAYPOINTS = 25; const MAX_WAYPOINTS_TO_DISPLAY = 4; @@ -63,6 +67,18 @@ const propTypes = { /** Time when the token will expire in ISO 8601 */ expiration: PropTypes.string, }), + + /** React Navigation route */ + route: PropTypes.shape({ + /** Params from the route */ + params: PropTypes.shape({ + /** The type of IOU report, i.e. bill, request, send */ + iouType: PropTypes.string, + + /** The report ID of the IOU */ + reportID: PropTypes.string, + }), + }).isRequired, }; const defaultProps = { @@ -75,13 +91,14 @@ const defaultProps = { }, }; -function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken}) { +function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken, route}) { const [shouldShowGradient, setShouldShowGradient] = useState(false); const [scrollContainerHeight, setScrollContainerHeight] = useState(0); const [scrollContentHeight, setScrollContentHeight] = useState(0); const {isOffline} = useNetwork(); const {translate} = useLocalize(); + const isEditing = lodashGet(route, 'path', '').includes('address'); const reportID = lodashGet(report, 'reportID', ''); const waypoints = useMemo(() => lodashGet(transaction, 'comment.waypoints', {}), [transaction]); const previousWaypoints = usePrevious(waypoints); @@ -170,7 +187,20 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken}) useEffect(updateGradientVisibility, [scrollContainerHeight, scrollContentHeight]); - return ( + const navigateBack = () => { + Navigation.goBack(isEditing ? ROUTES.getMoneyRequestConfirmationRoute(iouType, reportID) : null); + }; + + const navigateToNextPage = () => { + if (isEditing) { + Navigation.goBack(ROUTES.getMoneyRequestConfirmationRoute(iouType, reportID)); + return; + } + + IOU.navigateToNextPage(iou, iouType, reportID, report); + }; + + const content = ( {!isOffline && Boolean(mapboxAccessToken.token) ? ( - ) : ( @@ -265,12 +296,35 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken})