diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml
index 755ab6dbaa60..6ded44d7059f 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 }}/NewExpensifyAdHoc.dmg
+ DESKTOP_LINK: https://ad-hoc-expensify-cash.s3.amazonaws.com/desktop/${{ env.PULL_REQUEST_NUMBER }}/NewExpensify.dmg
IOS_LINK: ${{steps.get_ios_path.outputs.ios_path}}
WEB_LINK: https://${{ env.PULL_REQUEST_NUMBER }}.pr-testing.expensify.com
diff --git a/Cloudflare_CA.crt b/Cloudflare_CA.crt
new file mode 100644
index 000000000000..f02f49a951fc
Binary files /dev/null and b/Cloudflare_CA.crt differ
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 1867a8cf85d2..f957ea7c5854 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 1001037002
- versionName "1.3.70-2"
+ versionCode 1001037105
+ versionName "1.3.71-5"
}
flavorDimensions "default"
diff --git a/config/electronBuilder.config.js b/config/electronBuilder.config.js
index a5478dbd8f78..da87c93ee367 100644
--- a/config/electronBuilder.config.js
+++ b/config/electronBuilder.config.js
@@ -21,24 +21,6 @@ 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) {
@@ -50,8 +32,8 @@ if (!isCorrectElectronEnv) {
* It can be used to create local builds of the same, by omitting the `--publish` flag
*/
module.exports = {
- appId: appIds[process.env.ELECTRON_ENV],
- productName: productNames[process.env.ELECTRON_ENV],
+ appId: 'com.expensifyreactnative.chat',
+ productName: 'New Expensify',
extraMetadata: {
version,
},
@@ -64,8 +46,8 @@ module.exports = {
type: 'distribution',
},
dmg: {
- title: productNames[process.env.ELECTRON_ENV],
- artifactName: artifactNames[process.env.ELECTRON_ENV],
+ title: 'New Expensify',
+ artifactName: 'NewExpensify.dmg',
internetEnabled: true,
},
publish: [
@@ -83,7 +65,7 @@ module.exports = {
output: 'desktop-build',
},
protocols: {
- name: productNames[process.env.ELECTRON_ENV],
+ name: 'New Expensify',
schemes: ['new-expensify'],
},
};
diff --git a/docs/assets/js/main.js b/docs/assets/js/main.js
index 01ebb00b288c..f0f335536c20 100644
--- a/docs/assets/js/main.js
+++ b/docs/assets/js/main.js
@@ -206,13 +206,6 @@ window.addEventListener('DOMContentLoaded', () => {
// If there is a fixed article scroll container, set to calculate titles' offset
scrollContainer: 'content-area',
-
- // onclick function to apply to all links in toc. will be called with
- // the event as the first parameter, and this can be used to stop,
- // propagation, prevent default or perform action
- onClick() {
- toggleHeaderMenu();
- },
});
}
@@ -226,6 +219,18 @@ window.addEventListener('DOMContentLoaded', () => {
const articleContent = document.getElementById('article-content');
const lhnContent = document.getElementById('lhn-content');
+
+ // This event listener checks if a link clicked in the LHN points to some section of the same page and toggles
+ // the LHN menu in responsive view.
+ lhnContent.addEventListener('click', (event) => {
+ const clickedLink = event.target;
+ if (clickedLink) {
+ const href = clickedLink.getAttribute('href');
+ if (href && href.startsWith('#') && !!document.getElementById(href.slice(1))) {
+ toggleHeaderMenu();
+ }
+ }
+ });
lhnContent.addEventListener('wheel', (e) => {
const scrollTop = lhnContent.scrollTop;
const isScrollingPastLHNTop = e.deltaY < 0 && scrollTop === 0;
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 9e4501eddea5..07e1cfae80ac 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -19,7 +19,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 1.3.70
+ 1.3.71
CFBundleSignature
????
CFBundleURLTypes
@@ -40,7 +40,7 @@
CFBundleVersion
- 1.3.70.2
+ 1.3.71.5
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index fd93684a1da3..49d12cf93594 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -15,10 +15,10 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 1.3.70
+ 1.3.71
CFBundleSignature
????
CFBundleVersion
- 1.3.70.2
+ 1.3.71.5
diff --git a/package-lock.json b/package-lock.json
index 0ba372b22745..68ea17fc20b8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "new.expensify",
- "version": "1.3.70-2",
+ "version": "1.3.71-5",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "new.expensify",
- "version": "1.3.70-2",
+ "version": "1.3.71-5",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@@ -52,7 +52,6 @@
"domhandler": "^4.3.0",
"expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#35bff866a8d345b460ea6256f0a0f0a8a7f81086",
"fbjs": "^3.0.2",
- "focus-trap-react": "^10.2.1",
"htmlparser2": "^7.2.0",
"idb-keyval": "^6.2.1",
"jest-when": "^3.5.2",
@@ -70,6 +69,7 @@
"react-collapse": "^5.1.0",
"react-content-loader": "^6.1.0",
"react-dom": "18.1.0",
+ "react-error-boundary": "^4.0.11",
"react-map-gl": "^7.1.3",
"react-native": "0.72.3",
"react-native-blob-util": "^0.17.3",
@@ -90,10 +90,10 @@
"react-native-linear-gradient": "^2.8.1",
"react-native-localize": "^2.2.6",
"react-native-modal": "^13.0.0",
- "react-native-onyx": "1.0.76",
+ "react-native-onyx": "1.0.77",
"react-native-pager-view": "^6.2.0",
"react-native-pdf": "^6.7.1",
- "react-native-performance": "^4.0.0",
+ "react-native-performance": "^5.1.0",
"react-native-permissions": "^3.0.1",
"react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#eae05855286dc699954415cc1d629bfd8e8e47e2",
"react-native-plaid-link-sdk": "^10.0.0",
@@ -103,7 +103,7 @@
"react-native-render-html": "6.3.1",
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "3.21.0",
- "react-native-svg": "^13.9.0",
+ "react-native-svg": "^13.13.0",
"react-native-tab-view": "^3.5.2",
"react-native-url-polyfill": "^2.0.0",
"react-native-view-shot": "^3.6.0",
@@ -28295,28 +28295,6 @@
"readable-stream": "^2.3.6"
}
},
- "node_modules/focus-trap": {
- "version": "7.5.2",
- "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.2.tgz",
- "integrity": "sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==",
- "dependencies": {
- "tabbable": "^6.2.0"
- }
- },
- "node_modules/focus-trap-react": {
- "version": "10.2.1",
- "resolved": "https://registry.npmjs.org/focus-trap-react/-/focus-trap-react-10.2.1.tgz",
- "integrity": "sha512-UrAKOn52lvfHF6lkUMfFhlQxFgahyNW5i6FpHWkDxAeD4FSk3iwx9n4UEA4Sims0G5WiGIi0fAyoq3/UVeNCYA==",
- "dependencies": {
- "focus-trap": "^7.5.2",
- "tabbable": "^6.2.0"
- },
- "peerDependencies": {
- "prop-types": "^15.8.1",
- "react": ">=16.3.0",
- "react-dom": ">=16.3.0"
- }
- },
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
@@ -40210,6 +40188,17 @@
"react": "^18.1.0"
}
},
+ "node_modules/react-error-boundary": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.11.tgz",
+ "integrity": "sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5"
+ },
+ "peerDependencies": {
+ "react": ">=16.13.1"
+ }
+ },
"node_modules/react-freeze": {
"version": "1.0.3",
"license": "MIT",
@@ -40567,9 +40556,9 @@
}
},
"node_modules/react-native-onyx": {
- "version": "1.0.76",
- "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.76.tgz",
- "integrity": "sha512-mcMlYQCo1B/kom+4hu7CQKKLwvPFjQAJsVIzV2s9aa8XKNlcnYiJbfuM6RSJ1fFmSIeud4Y66rhv4/oWUkSl5A==",
+ "version": "1.0.77",
+ "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.77.tgz",
+ "integrity": "sha512-HmeS1Pz/BkKNbYuhWULC9I0VRBDt8yadG0ZFIW6wuZ+VajhjD960qh7Il1+XzEBI6Vb4d7BZkPcad87ad1IEOQ==",
"dependencies": {
"ascii-table": "0.0.9",
"fast-equals": "^4.0.3",
@@ -40583,7 +40572,7 @@
"idb-keyval": "^6.2.1",
"react": ">=18.1.0",
"react-native-device-info": "^10.3.0",
- "react-native-performance": "^4.0.0",
+ "react-native-performance": "^5.1.0",
"react-native-quick-sqlite": "^8.0.0-beta.2"
},
"peerDependenciesMeta": {
@@ -40625,8 +40614,9 @@
}
},
"node_modules/react-native-performance": {
- "version": "4.0.0",
- "license": "MIT",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/react-native-performance/-/react-native-performance-5.1.0.tgz",
+ "integrity": "sha512-rq/YBf0/GptSOM/Lj64/1yRq8uN2YE0psFB16wFbYBbTcIEp/0rrgN2HyS5lhvfBOFgKoDRWQ53jHSCb+QJ5eA==",
"peerDependencies": {
"react-native": "*"
}
@@ -40783,8 +40773,9 @@
}
},
"node_modules/react-native-svg": {
- "version": "13.9.0",
- "license": "MIT",
+ "version": "13.13.0",
+ "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.13.0.tgz",
+ "integrity": "sha512-L8y8uEiMG0Tr++Nb2+24wlMuv18+bmq/CMoFFtTUlEqVvGCoK2ea8WamPl/9bV8gjL+Rngg5NqEBvKS23sbYoA==",
"dependencies": {
"css-select": "^5.1.0",
"css-tree": "^1.1.3"
@@ -44692,11 +44683,6 @@
"dev": true,
"license": "BSD-3-Clause"
},
- "node_modules/tabbable": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
- "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
- },
"node_modules/table": {
"version": "6.8.1",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
@@ -67708,23 +67694,6 @@
"readable-stream": "^2.3.6"
}
},
- "focus-trap": {
- "version": "7.5.2",
- "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.2.tgz",
- "integrity": "sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==",
- "requires": {
- "tabbable": "^6.2.0"
- }
- },
- "focus-trap-react": {
- "version": "10.2.1",
- "resolved": "https://registry.npmjs.org/focus-trap-react/-/focus-trap-react-10.2.1.tgz",
- "integrity": "sha512-UrAKOn52lvfHF6lkUMfFhlQxFgahyNW5i6FpHWkDxAeD4FSk3iwx9n4UEA4Sims0G5WiGIi0fAyoq3/UVeNCYA==",
- "requires": {
- "focus-trap": "^7.5.2",
- "tabbable": "^6.2.0"
- }
- },
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
@@ -75785,6 +75754,14 @@
"scheduler": "^0.22.0"
}
},
+ "react-error-boundary": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.11.tgz",
+ "integrity": "sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw==",
+ "requires": {
+ "@babel/runtime": "^7.12.5"
+ }
+ },
"react-freeze": {
"version": "1.0.3",
"requires": {}
@@ -76116,9 +76093,9 @@
}
},
"react-native-onyx": {
- "version": "1.0.76",
- "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.76.tgz",
- "integrity": "sha512-mcMlYQCo1B/kom+4hu7CQKKLwvPFjQAJsVIzV2s9aa8XKNlcnYiJbfuM6RSJ1fFmSIeud4Y66rhv4/oWUkSl5A==",
+ "version": "1.0.77",
+ "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.77.tgz",
+ "integrity": "sha512-HmeS1Pz/BkKNbYuhWULC9I0VRBDt8yadG0ZFIW6wuZ+VajhjD960qh7Il1+XzEBI6Vb4d7BZkPcad87ad1IEOQ==",
"requires": {
"ascii-table": "0.0.9",
"fast-equals": "^4.0.3",
@@ -76141,7 +76118,9 @@
}
},
"react-native-performance": {
- "version": "4.0.0",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/react-native-performance/-/react-native-performance-5.1.0.tgz",
+ "integrity": "sha512-rq/YBf0/GptSOM/Lj64/1yRq8uN2YE0psFB16wFbYBbTcIEp/0rrgN2HyS5lhvfBOFgKoDRWQ53jHSCb+QJ5eA==",
"requires": {}
},
"react-native-performance-flipper-reporter": {
@@ -76238,7 +76217,9 @@
}
},
"react-native-svg": {
- "version": "13.9.0",
+ "version": "13.13.0",
+ "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.13.0.tgz",
+ "integrity": "sha512-L8y8uEiMG0Tr++Nb2+24wlMuv18+bmq/CMoFFtTUlEqVvGCoK2ea8WamPl/9bV8gjL+Rngg5NqEBvKS23sbYoA==",
"requires": {
"css-select": "^5.1.0",
"css-tree": "^1.1.3"
@@ -78848,11 +78829,6 @@
"version": "2.0.15",
"dev": true
},
- "tabbable": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
- "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
- },
"table": {
"version": "6.8.1",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
diff --git a/package.json b/package.json
index 97621503eb6f..72574455719b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.3.70-2",
+ "version": "1.3.71-5",
"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.",
@@ -94,7 +94,6 @@
"domhandler": "^4.3.0",
"expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#35bff866a8d345b460ea6256f0a0f0a8a7f81086",
"fbjs": "^3.0.2",
- "focus-trap-react": "^10.2.1",
"htmlparser2": "^7.2.0",
"idb-keyval": "^6.2.1",
"jest-when": "^3.5.2",
@@ -113,6 +112,7 @@
"react-content-loader": "^6.1.0",
"react-dom": "18.1.0",
"react-map-gl": "^7.1.3",
+ "react-error-boundary": "^4.0.11",
"react-native": "0.72.3",
"react-native-blob-util": "^0.17.3",
"react-native-collapsible": "^1.6.0",
@@ -132,10 +132,10 @@
"react-native-linear-gradient": "^2.8.1",
"react-native-localize": "^2.2.6",
"react-native-modal": "^13.0.0",
- "react-native-onyx": "1.0.76",
+ "react-native-onyx": "1.0.77",
"react-native-pager-view": "^6.2.0",
"react-native-pdf": "^6.7.1",
- "react-native-performance": "^4.0.0",
+ "react-native-performance": "^5.1.0",
"react-native-permissions": "^3.0.1",
"react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#eae05855286dc699954415cc1d629bfd8e8e47e2",
"react-native-plaid-link-sdk": "^10.0.0",
@@ -145,7 +145,7 @@
"react-native-render-html": "6.3.1",
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "3.21.0",
- "react-native-svg": "^13.9.0",
+ "react-native-svg": "^13.13.0",
"react-native-tab-view": "^3.5.2",
"react-native-url-polyfill": "^2.0.0",
"react-native-view-shot": "^3.6.0",
diff --git a/src/CONST.ts b/src/CONST.ts
index 1ef2f3e83246..93a17ac3c70d 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -293,8 +293,8 @@ const CONST = {
},
type: KEYBOARD_SHORTCUT_NAVIGATION_TYPE,
},
- NEW_GROUP: {
- descriptionKey: 'newGroup',
+ NEW_CHAT: {
+ descriptionKey: 'newChat',
shortcutKey: 'K',
modifiers: ['CTRL', 'SHIFT'],
trigger: {
@@ -1026,7 +1026,6 @@ const CONST = {
},
PAYMENT_METHODS: {
- PAYPAL: 'payPalMe',
DEBIT_CARD: 'debitCard',
BANK_ACCOUNT: 'bankAccount',
},
@@ -1042,7 +1041,6 @@ const CONST = {
PAYMENT_TYPE: {
ELSEWHERE: 'Elsewhere',
EXPENSIFY: 'Expensify',
- PAYPAL_ME: 'PayPal.me',
VBBA: 'ACH',
},
MONEY_REQUEST_TYPE: {
@@ -1170,6 +1168,7 @@ const CONST = {
SMALL_NORMAL: 'small-normal',
},
EXPENSIFY_CARD: {
+ BANK: 'Expensify Card',
FRAUD_TYPES: {
DOMAIN: 'domain',
INDIVIDUAL: 'individal',
@@ -1200,7 +1199,6 @@ const CONST = {
CARD_NUMBER: /^[0-9]{15,16}$/,
CARD_SECURITY_CODE: /^[0-9]{3,4}$/,
CARD_EXPIRATION_DATE: /^(0[1-9]|1[0-2])([^0-9])?([0-9]{4}|([0-9]{2}))$/,
- PAYPAL_ME_USERNAME: /^[a-zA-Z0-9]{1,20}$/,
ROOM_NAME: /^#[a-z0-9à-ÿ-]{1,80}$/,
// eslint-disable-next-line max-len, no-misleading-character-class
@@ -1342,6 +1340,7 @@ const CONST = {
SETTINGS: 'settings',
LEAVE_ROOM: 'leaveRoom',
WELCOME_MESSAGE: 'welcomeMessage',
+ PRIVATE_NOTES: 'privateNotes',
},
EDIT_REQUEST_FIELD: {
AMOUNT: 'amount',
@@ -2530,32 +2529,6 @@ const CONST = {
SEARCH_ISSUES: 'https://github.com/Expensify/App/issues',
},
- PAYPAL_SUPPORTED_CURRENCIES: [
- 'AUD',
- 'BRL',
- 'CAD',
- 'CZK',
- 'DKK',
- 'EUR',
- 'HKD',
- 'HUF',
- 'ILS',
- 'JPY',
- 'MYR',
- 'MXN',
- 'TWD',
- 'NZD',
- 'NOK',
- 'PHP',
- 'PLN',
- 'GBP',
- 'RUB',
- 'SGD',
- 'SEK',
- 'CHF',
- 'THB',
- 'USD',
- ],
CONCIERGE_TRAVEL_URL: 'https://community.expensify.com/discussion/7066/introducing-concierge-travel',
SCREEN_READER_STATES: {
ALL: 'all',
@@ -2624,6 +2597,9 @@ const CONST = {
DISABLED: 'DISABLED',
},
TAB: {
+ NEW_CHAT_TAB_ID: 'NewChatTab',
+ NEW_CHAT: 'chat',
+ NEW_ROOM: 'room',
RECEIPT_TAB_ID: 'ReceiptTab',
MANUAL: 'manual',
SCAN: 'scan',
diff --git a/src/Expensify.js b/src/Expensify.js
index 1086bd32cff9..fba65e42c06c 100644
--- a/src/Expensify.js
+++ b/src/Expensify.js
@@ -30,7 +30,6 @@ import KeyboardShortcutsModal from './components/KeyboardShortcutsModal';
import AppleAuthWrapper from './components/SignInButtons/AppleAuthWrapper';
import EmojiPicker from './components/EmojiPicker/EmojiPicker';
import * as EmojiPickerAction from './libs/actions/EmojiPickerAction';
-import DownloadAppModal from './components/DownloadAppModal';
import DeeplinkWrapper from './components/DeeplinkWrapper';
// This lib needs to be imported, but it has nothing to export since all it contains is an Onyx connection
@@ -193,7 +192,6 @@ function Expensify(props) {
{shouldInit && (
<>
-
diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index 2e0b75910bae..314685fae94f 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -87,13 +87,7 @@ const ONYXKEYS = {
SESSION: 'session',
BETAS: 'betas',
- /** Denotes if the Download App Banner has been dismissed */
- SHOW_DOWNLOAD_APP_BANNER: 'showDownloadAppBanner',
-
/** NVP keys
- * Contains the user's payPalMe data */
- PAYPAL: 'paypal',
-
/** Contains the user preference for the LHN priority mode */
NVP_PRIORITY_MODE: 'nvp_priorityMode',
@@ -284,12 +278,12 @@ const ONYXKEYS = {
MONEY_REQUEST_AMOUNT_FORM: 'moneyRequestAmountForm',
MONEY_REQUEST_DATE_FORM: 'moneyRequestCreatedForm',
NEW_CONTACT_METHOD_FORM: 'newContactMethodForm',
- PAYPAL_FORM: 'payPalForm',
WAYPOINT_FORM: 'waypointForm',
WAYPOINT_FORM_DRAFT: 'waypointFormDraft',
SETTINGS_STATUS_SET_FORM: 'settingsStatusSetForm',
SETTINGS_STATUS_CLEAR_AFTER_FORM: 'settingsStatusClearAfterForm',
SETTINGS_STATUS_SET_CLEAR_AFTER_FORM: 'settingsStatusSetClearAfterForm',
+ PRIVATE_NOTES_FORM: 'privateNotesForm',
I_KNOW_A_TEACHER_FORM: 'iKnowTeacherForm',
INTRO_SCHOOL_PRINCIPAL_FORM: 'introSchoolPrincipalForm',
},
@@ -306,7 +300,6 @@ type OnyxValues = {
[ONYXKEYS.ACTIVE_CLIENTS]: string[];
[ONYXKEYS.DEVICE_ID]: string;
[ONYXKEYS.IS_SIDEBAR_LOADED]: boolean;
- [ONYXKEYS.SHOW_DOWNLOAD_APP_BANNER]: boolean;
[ONYXKEYS.PERSISTED_REQUESTS]: OnyxTypes.Request[];
[ONYXKEYS.QUEUED_ONYX_UPDATES]: OnyxTypes.QueuedOnyxUpdates;
[ONYXKEYS.CURRENT_DATE]: string;
@@ -327,7 +320,6 @@ type OnyxValues = {
[ONYXKEYS.LOGIN_LIST]: OnyxTypes.Login;
[ONYXKEYS.SESSION]: OnyxTypes.Session;
[ONYXKEYS.BETAS]: OnyxTypes.Beta[];
- [ONYXKEYS.PAYPAL]: OnyxTypes.Paypal;
[ONYXKEYS.NVP_PRIORITY_MODE]: ValueOf;
[ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE]: OnyxTypes.BlockedFromConcierge;
[ONYXKEYS.NVP_PRIVATE_PUSH_NOTIFICATION_ID]: string;
@@ -419,7 +411,6 @@ type OnyxValues = {
[ONYXKEYS.FORMS.MONEY_REQUEST_DATE_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.MONEY_REQUEST_DATE_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.NEW_CONTACT_METHOD_FORM]: OnyxTypes.Form;
- [ONYXKEYS.FORMS.PAYPAL_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.WAYPOINT_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.WAYPOINT_FORM_DRAFT]: OnyxTypes.Form;
[ONYXKEYS.FORMS.SETTINGS_STATUS_SET_FORM]: OnyxTypes.Form;
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 1133dcec8e9a..2c37116db395 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -13,7 +13,6 @@ type ParseReportRouteParams = {
const REPORT = 'r';
const IOU_REQUEST = 'request/new';
-const IOU_BILL = 'split/new';
const IOU_SEND = 'send/new';
const NEW_TASK = 'new/task';
const SETTINGS_PERSONAL_DETAILS = 'settings/profile/personal-details';
@@ -49,7 +48,6 @@ export default {
SETTINGS_ABOUT: 'settings/about',
SETTINGS_APP_DOWNLOAD_LINKS: 'settings/about/app-download-links',
SETTINGS_WALLET: 'settings/wallet',
- SETTINGS_ADD_PAYPAL_ME: 'settings/wallet/add-paypal-me',
SETTINGS_ADD_DEBIT_CARD: 'settings/wallet/add-debit-card',
SETTINGS_ADD_BANK_ACCOUNT: 'settings/wallet/add-bank-account',
SETTINGS_ENABLE_PAYMENTS: 'settings/wallet/enable-payments',
@@ -67,8 +65,9 @@ export default {
SETTINGS_2FA: 'settings/security/two-factor-auth',
SETTINGS_STATUS,
SETTINGS_STATUS_SET,
- NEW_GROUP: 'new/group',
+ NEW: 'new',
NEW_CHAT: 'new/chat',
+ NEW_ROOM: 'new/room',
NEW_TASK,
REPORT,
REPORT_WITH_ID: 'r/:reportID?/:reportActionID?',
@@ -86,7 +85,6 @@ export default {
CONCIERGE: 'concierge',
IOU_REQUEST,
- IOU_BILL,
IOU_SEND,
// To see the available iouType, please refer to CONST.IOU.MONEY_REQUEST_TYPE
@@ -174,6 +172,14 @@ export default {
GOOGLE_SIGN_IN: 'sign-in-with-google',
DESKTOP_SIGN_IN_REDIRECT: 'desktop-signin-redirect',
+ // Routes related to private notes added to the report
+ PRIVATE_NOTES_VIEW: 'r/:reportID/notes/:accountID',
+ getPrivateNotesViewRoute: (reportID: string, accountID: string | number) => `r/${reportID}/notes/${accountID}`,
+ PRIVATE_NOTES_LIST: 'r/:reportID/notes',
+ getPrivateNotesListRoute: (reportID: string) => `r/${reportID}/notes`,
+ PRIVATE_NOTES_EDIT: 'r/:reportID/notes/:accountID/edit',
+ getPrivateNotesEditRoute: (reportID: string, accountID: string | number) => `r/${reportID}/notes/${accountID}/edit`,
+
// This is a special validation URL that will take the user to /workspace/new after validation. This is used
// when linking users from e.com in order to share a session in this app.
ENABLE_PAYMENTS: 'enable-payments',
diff --git a/src/components/AddPaymentMethodMenu.js b/src/components/AddPaymentMethodMenu.js
index 7f1544a758f4..399247a35676 100644
--- a/src/components/AddPaymentMethodMenu.js
+++ b/src/components/AddPaymentMethodMenu.js
@@ -10,7 +10,6 @@ import withWindowDimensions from './withWindowDimensions';
import Permissions from '../libs/Permissions';
import PopoverMenu from './PopoverMenu';
import refPropTypes from './refPropTypes';
-import paypalMeDataPropTypes from './paypalMeDataPropTypes';
const propTypes = {
/** Should the component be visible? */
@@ -25,12 +24,6 @@ const propTypes = {
vertical: PropTypes.number,
}),
- /** Account details for PayPal.Me */
- payPalMeData: paypalMeDataPropTypes,
-
- /** Should we show the Paypal option */
- shouldShowPaypal: PropTypes.bool,
-
/** List of betas available to current user */
betas: PropTypes.arrayOf(PropTypes.string),
@@ -42,8 +35,6 @@ const propTypes = {
const defaultProps = {
anchorPosition: {},
- payPalMeData: {},
- shouldShowPaypal: true,
betas: [],
anchorRef: () => {},
};
@@ -73,15 +64,6 @@ function AddPaymentMethodMenu(props) {
},
]
: []),
- ...(props.shouldShowPaypal && !props.payPalMeData.description
- ? [
- {
- text: props.translate('common.payPalMe'),
- icon: Expensicons.PayPal,
- onSelected: () => props.onItemSelected(CONST.PAYMENT_METHODS.PAYPAL),
- },
- ]
- : []),
]}
withoutOverlay
/>
@@ -96,9 +78,6 @@ export default compose(
withWindowDimensions,
withLocalize,
withOnyx({
- payPalMeData: {
- key: ONYXKEYS.PAYPAL,
- },
betas: {
key: ONYXKEYS.BETAS,
},
diff --git a/src/components/AnimatedStep/index.js b/src/components/AnimatedStep/index.js
index a8b9b80fcc0e..5b0dc8bc78fa 100644
--- a/src/components/AnimatedStep/index.js
+++ b/src/components/AnimatedStep/index.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import * as Animatable from 'react-native-animatable';
import CONST from '../../CONST';
import styles from '../../styles/styles';
+import useNativeDriver from '../../libs/useNativeDriver';
const propTypes = {
/** Children to wrap in AnimatedStep. */
@@ -47,7 +48,7 @@ function AnimatedStep(props) {
}}
duration={CONST.ANIMATED_TRANSITION}
animation={getAnimationStyle(props.direction)}
- useNativeDriver
+ useNativeDriver={useNativeDriver}
style={props.style}
>
{props.children}
diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js
index d39906faf3a3..bbb0662132d2 100755
--- a/src/components/AttachmentModal.js
+++ b/src/components/AttachmentModal.js
@@ -25,6 +25,7 @@ import HeaderGap from './HeaderGap';
import SafeAreaConsumer from './SafeAreaConsumer';
import addEncryptedAuthTokenToURL from '../libs/addEncryptedAuthTokenToURL';
import reportPropTypes from '../pages/reportPropTypes';
+import useNativeDriver from '../libs/useNativeDriver';
/**
* Modal render prop component that exposes modal launching triggers that can be used
@@ -294,7 +295,7 @@ function AttachmentModal(props) {
Animated.timing(confirmButtonFadeAnimation, {
toValue,
duration: 100,
- useNativeDriver: true,
+ useNativeDriver,
}).start();
},
[confirmButtonFadeAnimation],
diff --git a/src/components/Attachments/AttachmentCarousel/extractAttachmentsFromReport.js b/src/components/Attachments/AttachmentCarousel/extractAttachmentsFromReport.js
index d5da25c89576..8a623a44709f 100644
--- a/src/components/Attachments/AttachmentCarousel/extractAttachmentsFromReport.js
+++ b/src/components/Attachments/AttachmentCarousel/extractAttachmentsFromReport.js
@@ -59,6 +59,7 @@ function extractAttachmentsFromReport(report, reportActions) {
isAuthTokenRequired: true,
file: {name: transaction.filename},
isReceipt: true,
+ transactionID,
});
return;
}
diff --git a/src/components/Attachments/AttachmentCarousel/index.js b/src/components/Attachments/AttachmentCarousel/index.js
index 5c731a0ccfee..574cb496d02f 100644
--- a/src/components/Attachments/AttachmentCarousel/index.js
+++ b/src/components/Attachments/AttachmentCarousel/index.js
@@ -19,6 +19,7 @@ import BlockingView from '../../BlockingViews/BlockingView';
import * as Illustrations from '../../Icon/Illustrations';
import variables from '../../../styles/variables';
import * as DeviceCapabilities from '../../../libs/DeviceCapabilities';
+import * as ReportActionsUtils from '../../../libs/ReportActionsUtils';
const viewabilityConfig = {
// To facilitate paging through the attachments, we want to consider an item "viewable" when it is
@@ -38,13 +39,25 @@ function AttachmentCarousel({report, reportActions, source, onNavigate, setDownl
const [activeSource, setActiveSource] = useState(source);
const [shouldShowArrows, setShouldShowArrows, autoHideArrows, cancelAutoHideArrows] = useCarouselArrows();
+ const compareImage = useCallback(
+ (attachment) => {
+ if (attachment.isReceipt) {
+ const action = ReportActionsUtils.getParentReportAction(report);
+ const transactionID = _.get(action, ['originalMessage', 'IOUTransactionID']);
+ return attachment.transactionID === transactionID;
+ }
+ return attachment.source === source;
+ },
+ [source, report],
+ );
+
useEffect(() => {
const attachmentsFromReport = extractAttachmentsFromReport(report, reportActions);
- const initialPage = _.findIndex(attachmentsFromReport, (a) => a.source === source);
+ const initialPage = _.findIndex(attachmentsFromReport, compareImage);
// Dismiss the modal when deleting an attachment during its display in preview.
- if (initialPage === -1 && _.find(attachments, (a) => a.source === source)) {
+ if (initialPage === -1 && _.find(attachments, compareImage)) {
Navigation.dismissModal();
} else {
setPage(initialPage);
@@ -57,7 +70,7 @@ function AttachmentCarousel({report, reportActions, source, onNavigate, setDownl
if (!_.isUndefined(attachmentsFromReport[initialPage])) onNavigate(attachmentsFromReport[initialPage]);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [report, reportActions, source]);
+ }, [reportActions, compareImage]);
/**
* Updates the page state when the user navigates between attachments
diff --git a/src/components/Attachments/AttachmentCarousel/index.native.js b/src/components/Attachments/AttachmentCarousel/index.native.js
index 95cda7c2f5c9..a7a2f35a2ccc 100644
--- a/src/components/Attachments/AttachmentCarousel/index.native.js
+++ b/src/components/Attachments/AttachmentCarousel/index.native.js
@@ -16,6 +16,7 @@ import * as Illustrations from '../../Icon/Illustrations';
import variables from '../../../styles/variables';
import compose from '../../../libs/compose';
import withLocalize from '../../withLocalize';
+import * as ReportActionsUtils from '../../../libs/ReportActionsUtils';
function AttachmentCarousel({report, reportActions, source, onNavigate, onClose, setDownloadButtonVisibility, translate}) {
const pagerRef = useRef(null);
@@ -27,13 +28,25 @@ function AttachmentCarousel({report, reportActions, source, onNavigate, onClose,
const [isPinchGestureRunning, setIsPinchGestureRunning] = useState(true);
const [shouldShowArrows, setShouldShowArrows, autoHideArrows, cancelAutoHideArrows] = useCarouselArrows();
+ const compareImage = useCallback(
+ (attachment) => {
+ if (attachment.isReceipt) {
+ const action = ReportActionsUtils.getParentReportAction(report);
+ const transactionID = _.get(action, ['originalMessage', 'IOUTransactionID']);
+ return attachment.transactionID === transactionID;
+ }
+ return attachment.source === source;
+ },
+ [source, report],
+ );
+
useEffect(() => {
const attachmentsFromReport = extractAttachmentsFromReport(report, reportActions);
- const initialPage = _.findIndex(attachmentsFromReport, (a) => a.source === source);
+ const initialPage = _.findIndex(attachmentsFromReport, compareImage);
// Dismiss the modal when deleting an attachment during its display in preview.
- if (initialPage === -1 && _.find(attachments, (a) => a.source === source)) {
+ if (initialPage === -1 && _.find(attachments, compareImage)) {
Navigation.dismissModal();
} else {
setPage(initialPage);
@@ -46,7 +59,7 @@ function AttachmentCarousel({report, reportActions, source, onNavigate, onClose,
if (!_.isUndefined(attachmentsFromReport[initialPage])) onNavigate(attachmentsFromReport[initialPage]);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [report, reportActions, source]);
+ }, [reportActions, compareImage]);
/**
* Updates the page state when the user navigates between attachments
diff --git a/src/components/AvatarWithImagePicker.js b/src/components/AvatarWithImagePicker.js
index aa50d6db574b..3a43ede5a8f4 100644
--- a/src/components/AvatarWithImagePicker.js
+++ b/src/components/AvatarWithImagePicker.js
@@ -23,6 +23,8 @@ import getImageResolution from '../libs/fileDownload/getImageResolution';
import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback';
import DotIndicatorMessage from './DotIndicatorMessage';
import * as Browser from '../libs/Browser';
+import withNavigationFocus, {withNavigationFocusPropTypes} from './withNavigationFocus';
+import compose from '../libs/compose';
const propTypes = {
/** Avatar source to display */
@@ -80,6 +82,7 @@ const propTypes = {
errors: PropTypes.object,
...withLocalizePropTypes,
+ ...withNavigationFocusPropTypes,
};
const defaultProps = {
@@ -129,6 +132,9 @@ class AvatarWithImagePicker extends React.Component {
}
componentDidUpdate(prevProps) {
+ if (!prevProps.isFocused && this.props.isFocused) {
+ this.setError(null, {});
+ }
if (!prevProps.isUploading && this.props.isUploading) {
this.animation.start();
} else if (prevProps.isUploading && !this.props.isUploading) {
@@ -350,4 +356,4 @@ class AvatarWithImagePicker extends React.Component {
AvatarWithImagePicker.propTypes = propTypes;
AvatarWithImagePicker.defaultProps = defaultProps;
-export default withLocalize(AvatarWithImagePicker);
+export default compose(withLocalize, withNavigationFocus)(AvatarWithImagePicker);
diff --git a/src/components/Button/index.js b/src/components/Button/index.js
index bfde528a4750..c16860344837 100644
--- a/src/components/Button/index.js
+++ b/src/components/Button/index.js
@@ -218,6 +218,7 @@ class Button extends Component {
this.props.icon && styles.textAlignLeft,
...this.props.textStyles,
]}
+ dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}}
>
{this.props.text}
diff --git a/src/components/ButtonWithDropdownMenu.js b/src/components/ButtonWithDropdownMenu.js
index 62eeb3030619..54d6c0deac5a 100644
--- a/src/components/ButtonWithDropdownMenu.js
+++ b/src/components/ButtonWithDropdownMenu.js
@@ -32,7 +32,7 @@ const propTypes = {
style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
/** Menu options to display */
- /** e.g. [{text: 'Pay with Expensify', icon: Wallet}, {text: 'PayPal', icon: PayPal}] */
+ /** e.g. [{text: 'Pay with Expensify', icon: Wallet}] */
options: PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.string.isRequired,
diff --git a/src/components/CollapsibleSection/index.js b/src/components/CollapsibleSection/index.js
index e9c3a90a7b30..7009d1905e1d 100644
--- a/src/components/CollapsibleSection/index.js
+++ b/src/components/CollapsibleSection/index.js
@@ -51,6 +51,7 @@ class CollapsibleSection extends React.Component {
{this.props.title}
diff --git a/src/components/ConfirmContent.js b/src/components/ConfirmContent.js
index 9a72d4e7d584..ab3e23d6b1c1 100644
--- a/src/components/ConfirmContent.js
+++ b/src/components/ConfirmContent.js
@@ -100,8 +100,8 @@ function ConfirmContent(props) {
diff --git a/src/components/ConfirmedRoute.js b/src/components/ConfirmedRoute.js
index 4bcdc4738a3c..dab30e60ca55 100644
--- a/src/components/ConfirmedRoute.js
+++ b/src/components/ConfirmedRoute.js
@@ -1,9 +1,9 @@
import React, {useEffect} from 'react';
import PropTypes from 'prop-types';
-import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import lodashGet from 'lodash/get';
+import lodashIsNil from 'lodash/isNil';
import _ from 'underscore';
import ONYXKEYS from '../ONYXKEYS';
import CONST from '../CONST';
@@ -13,9 +13,8 @@ import * as Expensicons from './Icon/Expensicons';
import theme from '../styles/themes/default';
import styles from '../styles/styles';
import transactionPropTypes from './transactionPropTypes';
-import BlockingView from './BlockingViews/BlockingView';
+import PendingMapView from './MapView/PendingMapView';
import useNetwork from '../hooks/useNetwork';
-import useLocalize from '../hooks/useLocalize';
import DistanceMapView from './DistanceMapView';
const propTypes = {
@@ -44,7 +43,7 @@ const getWaypointMarkers = (waypoints) => {
const lastWaypointIndex = numberOfWaypoints - 1;
return _.filter(
_.map(waypoints, (waypoint, key) => {
- if (!waypoint || waypoint.lng === undefined || waypoint.lat === undefined) {
+ if (!waypoint || lodashIsNil(waypoint.lat) || lodashIsNil(waypoint.lng)) {
return;
}
@@ -76,7 +75,6 @@ const getWaypointMarkers = (waypoints) => {
function ConfirmedRoute({mapboxAccessToken, transaction}) {
const {isOffline} = useNetwork();
- const {translate} = useLocalize();
const {route0: route} = transaction.routes || {};
const waypoints = lodashGet(transaction, 'comment.waypoints', {});
const coordinates = lodashGet(route, 'geometry.coordinates', []);
@@ -104,14 +102,7 @@ function ConfirmedRoute({mapboxAccessToken, transaction}) {
styleURL={CONST.MAPBOX.STYLE_URL}
/>
) : (
-
-
-
+
)}
>
);
diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js
index bf5a4cb9548b..966f700e25d4 100644
--- a/src/components/DistanceRequest.js
+++ b/src/components/DistanceRequest.js
@@ -2,8 +2,7 @@ import React, {useEffect, useMemo, useState, useRef} from 'react';
import {ScrollView, View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import lodashGet from 'lodash/get';
-import lodashHas from 'lodash/has';
-import lodashIsNull from 'lodash/isNull';
+import lodashIsNil from 'lodash/isNil';
import PropTypes from 'prop-types';
import _ from 'underscore';
@@ -32,7 +31,7 @@ import Button from './Button';
import DistanceMapView from './DistanceMapView';
import LinearGradient from './LinearGradient';
import * as Expensicons from './Icon/Expensicons';
-import BlockingView from './BlockingViews/BlockingView';
+import PendingMapView from './MapView/PendingMapView';
import DotIndicatorMessage from './DotIndicatorMessage';
import MenuItemWithTopDescription from './MenuItemWithTopDescription';
import {iouPropTypes} from '../pages/iou/propTypes';
@@ -109,15 +108,17 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken,
const lastWaypointIndex = numberOfWaypoints - 1;
const isLoadingRoute = lodashGet(transaction, 'comment.isLoading', false);
const hasRouteError = !!lodashGet(transaction, 'errorFields.route');
- const haveWaypointsChanged = !_.isEqual(previousWaypoints, waypoints);
- const doesRouteExist = lodashHas(transaction, 'routes.route0.geometry.coordinates');
+ const hasRoute = TransactionUtils.hasRoute(transaction);
const validatedWaypoints = TransactionUtils.getValidWaypoints(waypoints);
- const shouldFetchRoute = (!doesRouteExist || haveWaypointsChanged) && !isLoadingRoute && _.size(validatedWaypoints) > 1;
+ const previousValidatedWaypoints = usePrevious(validatedWaypoints);
+ const haveValidatedWaypointsChanged = !_.isEqual(previousValidatedWaypoints, validatedWaypoints);
+ const isRouteAbsentWithoutErrors = !hasRoute && !hasRouteError;
+ const shouldFetchRoute = (isRouteAbsentWithoutErrors || haveValidatedWaypointsChanged) && !isLoadingRoute && _.size(validatedWaypoints) > 1;
const waypointMarkers = useMemo(
() =>
_.filter(
_.map(waypoints, (waypoint, key) => {
- if (!waypoint || !lodashHas(waypoint, 'lat') || !lodashHas(waypoint, 'lng') || lodashIsNull(waypoint.lat) || lodashIsNull(waypoint.lng)) {
+ if (!waypoint || lodashIsNil(waypoint.lat) || lodashIsNil(waypoint.lng)) {
return;
}
@@ -283,14 +284,10 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken,
overlayStyle={styles.m4}
/>
) : (
-
-
-
+
)}