1 import { c } from 'ttag';
3 import clsx from '@proton/utils/clsx';
13 } from '../../utils/transfer';
14 import Buttons from './Buttons';
15 import DownloadLogsButton from './DownloadLogsButton';
16 import type { TransferManagerButtonProps } from './interfaces';
17 import type { Download, TransferType, Upload } from './transfer';
18 import useTransferControls from './useTransferControls';
20 type TransferManagerEntry = { transfer: Upload | Download; type: TransferType };
22 interface HeaderButtonProps {
23 entries: TransferManagerEntry[];
25 showDownloadLog: boolean;
28 const extractTransferFromEntry = ({ transfer }: TransferManagerEntry) => transfer;
30 const isInvalidForCancellation = (transfer: Upload | Download) =>
31 isTransferCanceled(transfer) ||
32 isTransferSkipped(transfer) ||
33 isTransferFailed(transfer) ||
34 isTransferFinalizing(transfer) ||
35 isTransferDone(transfer);
37 const HeaderButton = ({ entries, className, showDownloadLog = false }: HeaderButtonProps) => {
38 const transferManagerControls = useTransferControls();
40 const areAllActiveTransfersPaused = entries
41 .map(extractTransferFromEntry)
42 .filter(isTransferOngoing)
43 .every(isTransferPaused);
44 const hasOnlyInactiveTransfers = entries
45 .map(extractTransferFromEntry)
46 .every((transfer) => !isTransferOngoing(transfer));
49 * Pause icon gets priority over resume icon. Here are the rules:
51 * - mixed transfer –> pause
52 * - only in progress –> pause
53 * - cancelled or failed -> pause (disabled)
54 * – all *active* transfers are paused -> resume
56 const shouldDisplayResume = entries.length !== 0 && areAllActiveTransfersPaused && !hasOnlyInactiveTransfers;
58 const testIdPrefix = 'drive-transfers-manager:header-controls-';
60 const buttons: TransferManagerButtonProps[] = [
63 const ongoingEntries = entries.filter(({ transfer }) => isTransferOngoing(transfer));
64 if (shouldDisplayResume) {
65 return transferManagerControls.resumeTransfers(ongoingEntries);
68 return transferManagerControls.pauseTransfers(ongoingEntries);
70 disabled: hasOnlyInactiveTransfers,
71 title: shouldDisplayResume ? c('Action').t`Resume all` : c('Action').t`Pause all`,
72 iconName: shouldDisplayResume ? 'play' : 'pause',
73 testId: testIdPrefix + (shouldDisplayResume ? 'play' : 'pause'),
77 transferManagerControls.cancelTransfers(
78 entries.filter((entry) => !isInvalidForCancellation(entry.transfer))
81 // Only cancelled/failed/finalizing/done transfers -> cancel button disabled
82 disabled: entries.map(extractTransferFromEntry).every(isInvalidForCancellation),
83 title: c('Action').t`Cancel all`,
85 testId: testIdPrefix + 'cancel',
89 return transferManagerControls.restartTransfers(
90 entries.filter(({ transfer }) => {
91 return isTransferFailed(transfer);
96 * Restart enabled when there're failed transfers in the list. This also covers
97 * the case when theres only transfers in progress
99 disabled: !entries.map(extractTransferFromEntry).some(isTransferFailed),
100 title: c('Action').t`Restart all`,
101 iconName: 'arrow-rotate-right',
102 testId: testIdPrefix + 'restart',
107 <div className={clsx(['flex', 'flex-nowrap', 'justify-end', 'overflow-hidden', 'shrink-0', className])}>
108 <Buttons buttons={buttons} className="shrink-0">
109 {showDownloadLog && <DownloadLogsButton onClick={transferManagerControls.downloadLogs} />}
115 export default HeaderButton;