add file download location selection option for selected files and single file

This commit is contained in:
Abhinav 2024-01-18 14:16:57 +05:30
parent 4c7bb9edc2
commit 5802db5434
5 changed files with 137 additions and 15 deletions

View file

@ -128,7 +128,10 @@ export const FilesDownloadProgress: React.FC<FilesDownloadProgressProps> = ({
<Notification
key={attributes.collectionID}
horizontal="left"
sx={{ '&&': { bottom: `${index * 80 + 20}px` } }}
sx={{
'&&': { bottom: `${index * 80 + 20}px` },
zIndex: 1600,
}}
open={isFilesDownloadStarted(attributes)}
onClose={handleClose(attributes)}
keepOpenOnClick

View file

@ -11,7 +11,10 @@ import AutoSizer from 'react-virtualized-auto-sizer';
import PhotoViewer from 'components/PhotoViewer';
import { TRASH_SECTION } from 'constants/collection';
import { updateFileMsrcProps, updateFileSrcProps } from 'utils/photoFrame';
import { SelectedState } from 'types/gallery';
import {
SelectedState,
SetFilesDownloadProgressAttributesCreator,
} from 'types/gallery';
import { PublicCollectionGalleryContext } from 'utils/publicCollectionGallery';
import { useRouter } from 'next/router';
import { logError } from '@ente/shared/sentry';
@ -62,6 +65,7 @@ interface Props {
showAppDownloadBanner?: boolean;
setIsPhotoSwipeOpen?: (value: boolean) => void;
isInHiddenSection?: boolean;
setFilesDownloadProgressAttributesCreator?: SetFilesDownloadProgressAttributesCreator;
}
const PhotoFrame = ({
@ -81,6 +85,7 @@ const PhotoFrame = ({
showAppDownloadBanner,
setIsPhotoSwipeOpen,
isInHiddenSection,
setFilesDownloadProgressAttributesCreator,
}: Props) => {
const [open, setOpen] = useState(false);
const [currentIndex, setCurrentIndex] = useState<number>(0);
@ -607,6 +612,9 @@ const PhotoFrame = ({
enableDownload={enableDownload}
fileToCollectionsMap={fileToCollectionsMap}
collectionNameMap={collectionNameMap}
setFilesDownloadProgressAttributesCreator={
setFilesDownloadProgressAttributesCreator
}
/>
</Container>
);

View file

@ -8,12 +8,12 @@ import {
} from 'services/collectionService';
import { EnteFile } from 'types/file';
import {
downloadFile,
copyFileToClipboard,
getFileExtension,
getFileFromURL,
isSupportedRawFormat,
isRawFile,
downloadSingleFile,
} from 'utils/file';
import { logError } from '@ente/shared/sentry';
@ -58,6 +58,7 @@ import isElectron from 'is-electron';
import ReplayIcon from '@mui/icons-material/Replay';
import ImageEditorOverlay from './ImageEditorOverlay';
import EditIcon from '@mui/icons-material/Edit';
import { SetFilesDownloadProgressAttributesCreator } from 'types/gallery';
interface PhotoswipeFullscreenAPI {
enter: () => void;
@ -92,6 +93,7 @@ interface Iprops {
enableDownload: boolean;
fileToCollectionsMap: Map<number, number[]>;
collectionNameMap: Map<number, string>;
setFilesDownloadProgressAttributesCreator: SetFilesDownloadProgressAttributesCreator;
}
function PhotoViewer(props: Iprops) {
@ -259,7 +261,7 @@ function PhotoViewer(props: Iprops) {
`download-btn-${item.id}`
) as HTMLButtonElement;
const downloadFile = () => {
downloadFileHelper(photoSwipe.currItem);
downloadFileHelper(photoSwipe.currItem as unknown as EnteFile);
};
if (downloadLivePhotoBtn) {
@ -599,15 +601,17 @@ function PhotoViewer(props: Iprops) {
setShowImageEditorOverlay(false);
};
const downloadFileHelper = async (file) => {
const downloadFileHelper = async (file: EnteFile) => {
if (file && props.enableDownload) {
appContext.startLoading();
try {
await downloadFile(file);
const setSingleFileDownloadProgress =
props.setFilesDownloadProgressAttributesCreator(
file.metadata.title
);
await downloadSingleFile(file, setSingleFileDownloadProgress);
} catch (e) {
// do nothing
}
appContext.finishLoading();
}
};
@ -702,7 +706,9 @@ function PhotoViewer(props: Iprops) {
onClose={() =>
setConversionFailedNotificationOpen(false)
}
onClick={() => downloadFileHelper(photoSwipe.currItem)}
onClick={() =>
downloadFileHelper(photoSwipe.currItem as EnteFile)
}
/>
<Box
@ -746,7 +752,9 @@ function PhotoViewer(props: Iprops) {
className="pswp__button pswp__button--custom"
title={t('DOWNLOAD_OPTION')}
onClick={() =>
downloadFileHelper(photoSwipe.currItem)
downloadFileHelper(
photoSwipe.currItem as EnteFile
)
}>
<DownloadIcon />
</button>

View file

@ -1165,6 +1165,9 @@ export default function Gallery() {
files.length < 30 && !isInSearchMode
}
isInHiddenSection={isInHiddenSection}
setFilesDownloadProgressAttributesCreator={
setFilesDownloadProgressAttributesCreator
}
/>
)}
{selected.count > 0 &&

View file

@ -1,4 +1,8 @@
import { SelectedState } from 'types/gallery';
import {
SelectedState,
SetFilesDownloadProgressAttributes,
SetFilesDownloadProgressAttributesCreator,
} from 'types/gallery';
import {
EnteFile,
EncryptedEnteFile,
@ -625,9 +629,96 @@ export function getUniqueFiles(files: EnteFile[]) {
return uniqueFiles;
}
export async function downloadFilesWithProgress(
files: EnteFile[],
downloadDirPath: string,
setFilesDownloadProgressAttributes: SetFilesDownloadProgressAttributes
) {
if (!files.length) {
return;
}
const canceller = new AbortController();
const increaseSuccess = () => {
if (canceller.signal.aborted) return;
setFilesDownloadProgressAttributes((prev) => ({
...prev,
success: prev.success + 1,
}));
};
const increaseFailed = () => {
if (canceller.signal.aborted) return;
setFilesDownloadProgressAttributes((prev) => ({
...prev,
failed: prev.failed + 1,
}));
};
const isCancelled = () => canceller.signal.aborted;
setFilesDownloadProgressAttributes({
downloadDirPath,
success: 0,
failed: 0,
total: files.length,
canceller,
});
if (isElectron()) {
await downloadFilesDesktop(
files,
{ increaseSuccess, increaseFailed, isCancelled },
downloadDirPath
);
} else {
await downloadFiles(files, {
increaseSuccess,
increaseFailed,
isCancelled,
});
}
}
export async function downloadSelectedFiles(
files: EnteFile[],
setFilesDownloadProgressAttributes: SetFilesDownloadProgressAttributes
) {
if (!files.length) {
return;
}
let downloadDirPath: string;
if (isElectron()) {
downloadDirPath = await ElectronAPIs.selectDirectory();
if (!downloadDirPath) {
return;
}
}
await downloadFilesWithProgress(
files,
downloadDirPath,
setFilesDownloadProgressAttributes
);
}
export async function downloadSingleFile(
file: EnteFile,
setFilesDownloadProgressAttributes: SetFilesDownloadProgressAttributes
) {
let downloadDirPath: string;
if (isElectron()) {
downloadDirPath = await ElectronAPIs.selectDirectory();
if (!downloadDirPath) {
return;
}
}
await downloadFilesWithProgress(
[file],
downloadDirPath,
setFilesDownloadProgressAttributes
);
}
export async function downloadFiles(
files: EnteFile[],
progressBarUpdater?: {
progressBarUpdater: {
increaseSuccess: () => void;
increaseFailed: () => void;
isCancelled: () => boolean;
@ -869,7 +960,8 @@ export const handleFileOps = async (
files: EnteFile[];
}
| ((prev: { files: EnteFile[] }) => { files: EnteFile[] })
) => void
) => void,
setFilesDownloadProgressAttributesCreator: SetFilesDownloadProgressAttributesCreator
) => {
switch (ops) {
case FILE_OPS_TYPE.TRASH:
@ -881,9 +973,17 @@ export const handleFileOps = async (
case FILE_OPS_TYPE.HIDE:
await hideFilesHelper(files, setHiddenFileIds);
break;
case FILE_OPS_TYPE.DOWNLOAD:
await downloadFiles(files);
case FILE_OPS_TYPE.DOWNLOAD: {
const setSelectedFileDownloadProgressAttributes =
setFilesDownloadProgressAttributesCreator(
`${files.length} files`
);
await downloadSelectedFiles(
files,
setSelectedFileDownloadProgressAttributes
);
break;
}
case FILE_OPS_TYPE.FIX_TIME:
fixTimeHelper(files, setFixCreationTimeAttributes);
break;