diff --git a/src/libs/fileDownload/index.ios.ts b/src/libs/fileDownload/index.ios.ts index c98839670070..73392072d9fe 100644 --- a/src/libs/fileDownload/index.ios.ts +++ b/src/libs/fileDownload/index.ios.ts @@ -7,6 +7,22 @@ import CONST from '@src/CONST'; import {appendTimeToFileName, getFileName, getFileType, showGeneralErrorAlert, showPermissionErrorAlert, showSuccessAlert} from './FileUtils'; import type {FileDownload} from './types'; +const isUserCancelled = (err: unknown) => { + let msg = ''; + if (typeof err === 'string') { + msg = err.toLowerCase(); + } else if (err && typeof err === 'object') { + const errorMessage = (err as {message?: unknown}).message; + const errorError = (err as {error?: unknown}).error; + if (typeof errorMessage === 'string') { + msg = errorMessage.toLowerCase(); + } else if (typeof errorError === 'string') { + msg = errorError.toLowerCase(); + } + } + return /cancel|did not share/.test(msg); +}; + /** * Downloads the file to Documents section in iOS */ @@ -55,7 +71,11 @@ const postDownloadFile = (url: string, fileName?: string, formData?: FormData, o .then(() => RNFS.unlink(localPath)); }); }) - .catch(() => { + .catch((error) => { + // If the user cancels the iOS share/save dialog, we exit silently without showing an error + if (isUserCancelled(error)) { + return; + } if (!onDownloadFailed) { showGeneralErrorAlert(); } diff --git a/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx b/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx index 6730368a5320..37c250532c35 100644 --- a/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx +++ b/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx @@ -8,7 +8,6 @@ import ConfirmModal from '@components/ConfirmModal'; import DecisionModal from '@components/DecisionModal'; import EmptyStateComponent from '@components/EmptyStateComponent'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import * as Expensicons from '@components/Icon/Expensicons'; import LottieAnimations from '@components/LottieAnimations'; import RenderHTML from '@components/RenderHTML'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -20,7 +19,7 @@ import type {ListItem} from '@components/SelectionListWithSections/types'; import TableListItemSkeleton from '@components/Skeletons/TableRowSkeleton'; import Text from '@components/Text'; import useCleanupSelectedOptions from '@hooks/useCleanupSelectedOptions'; -import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; +import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useMobileSelectionMode from '@hooks/useMobileSelectionMode'; import useNetwork from '@hooks/useNetwork'; @@ -130,6 +129,7 @@ function WorkspacePerDiemPage({route}: WorkspacePerDiemPageProps) { const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, {canBeMissing: false}); const isMobileSelectionModeEnabled = useMobileSelectionMode(); const illustrations = useMemoizedLazyIllustrations(['PerDiem'] as const); + const expensifyIcons = useMemoizedLazyExpensifyIcons(['Gear', 'Table', 'Download', 'Trashcan'] as const); const [customUnit, allRatesArray, allSubRates] = useMemo(() => { const customUnits = getPerDiemCustomUnit(policy); @@ -275,14 +275,14 @@ function WorkspacePerDiemPage({route}: WorkspacePerDiemPageProps) { const menuItems = []; if (policy?.areCategoriesEnabled && hasEnabledOptions(policyCategories ?? {})) { menuItems.push({ - icon: Expensicons.Gear, + icon: expensifyIcons.Gear, text: translate('common.settings'), onSelected: openSettings, value: CONST.POLICY.SECONDARY_ACTIONS.SETTINGS, }); } menuItems.push({ - icon: Expensicons.Table, + icon: expensifyIcons.Table, text: translate('spreadsheet.importSpreadsheet'), onSelected: () => { if (isOffline) { @@ -295,30 +295,43 @@ function WorkspacePerDiemPage({route}: WorkspacePerDiemPageProps) { }); if (hasVisibleSubRates) { menuItems.push({ - icon: Expensicons.Download, + icon: expensifyIcons.Download, text: translate('spreadsheet.downloadCSV'), onSelected: () => { if (isOffline) { close(() => setIsOfflineModalVisible(true)); return; } - downloadPerDiemCSV(policyID, () => { - setIsDownloadFailureModalVisible(true); - }); + close(() => + downloadPerDiemCSV(policyID, () => { + setIsDownloadFailureModalVisible(true); + }), + ); }, value: CONST.POLICY.SECONDARY_ACTIONS.DOWNLOAD_CSV, }); } return menuItems; - }, [policy?.areCategoriesEnabled, policyCategories, translate, hasVisibleSubRates, openSettings, isOffline, policyID]); + }, [ + policy?.areCategoriesEnabled, + policyCategories, + translate, + hasVisibleSubRates, + openSettings, + isOffline, + policyID, + expensifyIcons.Gear, + expensifyIcons.Table, + expensifyIcons.Download, + ]); const getHeaderButtons = () => { const options: Array>> = []; if (shouldUseNarrowLayout ? canSelectMultiple : selectedPerDiem.length > 0) { options.push({ - icon: Expensicons.Trashcan, + icon: expensifyIcons.Trashcan, text: translate('workspace.perDiem.deleteRates', {count: selectedPerDiem.length}), value: CONST.POLICY.BULK_ACTION_TYPES.DELETE, onSelected: () => setDeletePerDiemConfirmModalVisible(true), diff --git a/src/pages/workspace/tags/ImportTagsOptionsPage.tsx b/src/pages/workspace/tags/ImportTagsOptionsPage.tsx index 883b6388fd5d..c855b0c4ca9b 100644 --- a/src/pages/workspace/tags/ImportTagsOptionsPage.tsx +++ b/src/pages/workspace/tags/ImportTagsOptionsPage.tsx @@ -15,6 +15,7 @@ import useOnyx from '@hooks/useOnyx'; import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; +import {close} from '@libs/actions/Modal'; import {cleanPolicyTags, downloadMultiLevelTagsCSV, downloadTagsCSV, setImportedSpreadsheetIsImportingMultiLevelTags} from '@libs/actions/Policy/Tag'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; import Navigation from '@libs/Navigation/Navigation'; @@ -111,13 +112,17 @@ function ImportTagsOptionsPage({route}: ImportTagsOptionsPageProps) { downloadMultiLevelTagsCSV( policyID, () => { - setIsDownloadFailureModalVisible(true); + close(() => { + setIsDownloadFailureModalVisible(true); + }); }, hasDependentTags, ); } else { downloadTagsCSV(policyID, () => { - setIsDownloadFailureModalVisible(true); + close(() => { + setIsDownloadFailureModalVisible(true); + }); }); } }} @@ -139,13 +144,17 @@ function ImportTagsOptionsPage({route}: ImportTagsOptionsPageProps) { downloadMultiLevelTagsCSV( policyID, () => { - setIsDownloadFailureModalVisible(true); + close(() => { + setIsDownloadFailureModalVisible(true); + }); }, hasDependentTags, ); } else { downloadTagsCSV(policyID, () => { - setIsDownloadFailureModalVisible(true); + close(() => { + setIsDownloadFailureModalVisible(true); + }); }); } }}