add file download location selection option for selected files and single file
This commit is contained in:
parent
4c7bb9edc2
commit
5802db5434
5 changed files with 137 additions and 15 deletions
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1165,6 +1165,9 @@ export default function Gallery() {
|
|||
files.length < 30 && !isInSearchMode
|
||||
}
|
||||
isInHiddenSection={isInHiddenSection}
|
||||
setFilesDownloadProgressAttributesCreator={
|
||||
setFilesDownloadProgressAttributesCreator
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{selected.count > 0 &&
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue