Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/libs/fileDownload/index.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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;
}
Comment on lines +76 to +78

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave a comment here to explain. Thanks 😄

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment added.

if (!onDownloadFailed) {
showGeneralErrorAlert();
}
Expand Down
33 changes: 23 additions & 10 deletions src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand All @@ -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,
});
}

Comment thread
Krishna2323 marked this conversation as resolved.
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<DropdownOption<DeepValueOf<typeof CONST.POLICY.BULK_ACTION_TYPES>>> = [];

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),
Expand Down
17 changes: 13 additions & 4 deletions src/pages/workspace/tags/ImportTagsOptionsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -111,13 +112,17 @@ function ImportTagsOptionsPage({route}: ImportTagsOptionsPageProps) {
downloadMultiLevelTagsCSV(
policyID,
() => {
setIsDownloadFailureModalVisible(true);
close(() => {
setIsDownloadFailureModalVisible(true);
});
},
hasDependentTags,
);
} else {
downloadTagsCSV(policyID, () => {
setIsDownloadFailureModalVisible(true);
close(() => {
setIsDownloadFailureModalVisible(true);
});
});
}
}}
Expand All @@ -139,13 +144,17 @@ function ImportTagsOptionsPage({route}: ImportTagsOptionsPageProps) {
downloadMultiLevelTagsCSV(
policyID,
() => {
setIsDownloadFailureModalVisible(true);
close(() => {
setIsDownloadFailureModalVisible(true);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I thought we only needed to wrap this callback with close to prevent overlap modal right 🤔 ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right here, we should only wrap the state update callback for better UX. Thanks for catching that. Updated

});
},
hasDependentTags,
);
} else {
downloadTagsCSV(policyID, () => {
setIsDownloadFailureModalVisible(true);
close(() => {
setIsDownloadFailureModalVisible(true);
});
});
}
}}
Expand Down
Loading