diff --git a/cspell.json b/cspell.json
index 80ef1951f2c2..8e4d47c57f00 100644
--- a/cspell.json
+++ b/cspell.json
@@ -516,6 +516,7 @@
"creditamount",
"creditcards",
"crios",
+ "csvexport",
"csvg",
"customairshipextender",
"customfield",
diff --git a/src/components/ExportDownloadStatusModal.tsx b/src/components/ExportDownloadStatusModal.tsx
index be5b2d107d97..a030222b4d1b 100644
--- a/src/components/ExportDownloadStatusModal.tsx
+++ b/src/components/ExportDownloadStatusModal.tsx
@@ -1,17 +1,22 @@
-import {hasSeenTourSelector} from '@selectors/Onboarding';
import React, {useEffect} from 'react';
import {View} from 'react-native';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
+import useEnvironment from '@hooks/useEnvironment';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePreviousDefined from '@hooks/usePreviousDefined';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
+import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL';
+import {isMobileSafari} from '@libs/Browser';
+import {getOldDotURLFromEnvironment} from '@libs/Environment/Environment';
import fileDownload from '@libs/fileDownload';
+import Navigation from '@libs/Navigation/Navigation';
+import addTrailingForwardSlash from '@libs/UrlUtils';
import {clearExportDownload, sendExportFileFromConcierge} from '@userActions/Export';
-import {navigateToConciergeChat} from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
import ActivityIndicator from './ActivityIndicator';
import Button from './Button';
import Modal from './Modal';
@@ -37,30 +42,44 @@ function ExportDownloadStatusModal({exportID, isVisible, onClose, failedBody}: E
// isSmallScreenWidth is needed here because the modal type depends on actual screen width, not layout mode
// eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
const {isSmallScreenWidth} = useResponsiveLayout();
- const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
+ const {login: currentUserLogin} = useCurrentUserPersonalDetails();
+ const {environment} = useEnvironment();
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
- const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
- const [betas] = useOnyx(ONYXKEYS.BETAS);
- const [isSelfTourViewed] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector});
+ const [encryptedAuthToken] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.encryptedAuthToken});
const [exportDownload] = useOnyx(`${ONYXKEYS.COLLECTION.EXPORT_DOWNLOAD}${exportID}`);
const displayedExport = usePreviousDefined(exportDownload);
const state = displayedExport?.state;
const shouldSendFromConcierge = displayedExport?.shouldSendFromConcierge;
- const downloadURL = displayedExport?.downloadURL;
+ const fileName = displayedExport?.fileName;
const isPreparing = state === CONST.EXPORT_DOWNLOAD.STATE.PREPARING && !shouldSendFromConcierge;
const isConcierge = !!shouldSendFromConcierge;
const isReady = state === CONST.EXPORT_DOWNLOAD.STATE.READY;
const isFailed = state === CONST.EXPORT_DOWNLOAD.STATE.FAILED;
+ // Build the secure download URL the same way downloadReportPDF does, so the host always follows
+ // the app's current environment (instead of the env baked into a backend-built URL) and authenticates
+ // via the encryptedAuthToken — no separate OldDot sign-in needed.
+ const downloadFile = () => {
+ if (!fileName || !currentUserLogin) {
+ return;
+ }
+ const baseURL = addTrailingForwardSlash(getOldDotURLFromEnvironment(environment));
+ const isCSV = fileName.endsWith('.csv');
+ const secureType = isCSV ? 'csvexport' : 'pdfreport';
+ const url = `${baseURL}secure?secureType=${secureType}&filename=${encodeURIComponent(fileName)}&downloadName=${encodeURIComponent(fileName)}&email=${encodeURIComponent(currentUserLogin)}`;
+ fileDownload(translate, addEncryptedAuthTokenToURL(url, encryptedAuthToken ?? '', true), fileName, '', isMobileSafari());
+ };
+
useEffect(() => {
- if (!isReady || !downloadURL || shouldSendFromConcierge) {
+ if (!isReady || !fileName || shouldSendFromConcierge) {
return;
}
- fileDownload(translate, downloadURL);
- }, [isReady, downloadURL, translate, shouldSendFromConcierge]);
+ downloadFile();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [isReady, fileName, shouldSendFromConcierge]);
const handleSendFromConcierge = () => {
sendExportFileFromConcierge(exportID, displayedExport ?? undefined);
@@ -68,14 +87,9 @@ function ExportDownloadStatusModal({exportID, isVisible, onClose, failedBody}: E
const handleGoToConcierge = () => {
onClose();
- navigateToConciergeChat(conciergeReportID, introSelected, currentUserAccountID, isSelfTourViewed, betas);
- };
-
- const handleDownloadFile = () => {
- if (!downloadURL) {
- return;
+ if (conciergeReportID) {
+ Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID: conciergeReportID}));
}
- fileDownload(translate, downloadURL);
};
const handleClose = () => {
@@ -89,15 +103,15 @@ function ExportDownloadStatusModal({exportID, isVisible, onClose, failedBody}: E
if (isPreparing) {
return (
<>
-
- {translate('exportDownload.preparingTitle')}
- {translate('exportDownload.preparingBody')}
+
+ {translate('exportDownload.preparingTitle')}
+
+
+ {translate('exportDownload.preparingBody')}