فهرست منبع

Add select functionality to shared albums (#1566)

Abhinav Kumar 1 سال پیش
والد
کامیت
cc8a1ae309

+ 1 - 7
apps/photos/src/components/PhotoFrame.tsx

@@ -12,7 +12,6 @@ import PhotoViewer from 'components/PhotoViewer';
 import { TRASH_SECTION } from 'constants/collection';
 import { updateFileMsrcProps, updateFileSrcProps } from 'utils/photoFrame';
 import { SelectedState } from 'types/gallery';
-import { PublicCollectionGalleryContext } from 'utils/publicCollectionGallery';
 import { useRouter } from 'next/router';
 import { logError } from '@ente/shared/sentry';
 import { addLogLine } from '@ente/shared/logging';
@@ -89,9 +88,6 @@ const PhotoFrame = ({
         [k: number]: boolean;
     }>({});
     const galleryContext = useContext(GalleryContext);
-    const publicCollectionGalleryContext = useContext(
-        PublicCollectionGalleryContext
-    );
     const [rangeStart, setRangeStart] = useState(null);
     const [currentHover, setCurrentHover] = useState(null);
     const [isShiftKeyPressed, setIsShiftKeyPressed] = useState(false);
@@ -315,9 +311,7 @@ const PhotoFrame = ({
             file={item}
             updateURL={updateURL(index)}
             onClick={onThumbnailClick(index)}
-            selectable={
-                !publicCollectionGalleryContext?.accessedThroughSharedURL
-            }
+            selectable={enableDownload}
             onSelect={handleSelect(
                 item.id,
                 item.ownerID === galleryContext.user?.id,

+ 49 - 0
apps/photos/src/components/pages/sharedAlbum/SelectedFileOptions.tsx

@@ -0,0 +1,49 @@
+import { useContext } from 'react';
+import { FluidContainer } from '@ente/shared/components/Container';
+import { SelectionBar } from '@ente/shared/components/Navbar/SelectionBar';
+import { AppContext } from 'pages/_app';
+import { Box, IconButton, Stack, Tooltip } from '@mui/material';
+import CloseIcon from '@mui/icons-material/Close';
+import DownloadIcon from '@mui/icons-material/Download';
+import { t } from 'i18next';
+import { formatNumber } from 'utils/number/format';
+
+interface Props {
+    count: number;
+    ownCount: number;
+    clearSelection: () => void;
+    downloadFilesHelper: () => void;
+}
+
+const SelectedFileOptions = ({
+    downloadFilesHelper,
+    count,
+    ownCount,
+    clearSelection,
+}: Props) => {
+    const { isMobile } = useContext(AppContext);
+
+    return (
+        <SelectionBar isMobile={isMobile}>
+            <FluidContainer>
+                <IconButton onClick={clearSelection}>
+                    <CloseIcon />
+                </IconButton>
+                <Box ml={1.5}>
+                    {formatNumber(count)} {t('SELECTED')}{' '}
+                    {ownCount !== count &&
+                        `(${formatNumber(ownCount)} ${t('YOURS')})`}
+                </Box>
+            </FluidContainer>
+            <Stack spacing={2} direction="row" mr={2}>
+                <Tooltip title={t('DOWNLOAD')}>
+                    <IconButton onClick={downloadFilesHelper}>
+                        <DownloadIcon />
+                    </IconButton>
+                </Tooltip>
+            </Stack>
+        </SelectionBar>
+    );
+};
+
+export default SelectedFileOptions;

+ 41 - 4
apps/photos/src/pages/shared-albums/index.tsx

@@ -16,7 +16,13 @@ import {
 } from 'services/publicCollectionService';
 import { Collection } from 'types/collection';
 import { EnteFile } from 'types/file';
-import { downloadFile, mergeMetadata, sortFiles } from 'utils/file';
+import {
+    downloadFile,
+    downloadFiles,
+    getSelectedFiles,
+    mergeMetadata,
+    sortFiles,
+} from 'utils/file';
 import { AppContext } from 'pages/_app';
 import { PublicCollectionGalleryContext } from 'utils/publicCollectionGallery';
 import { CustomError, parseSharingErrorCodes } from '@ente/shared/error';
@@ -52,7 +58,7 @@ import UploadButton from 'components/Upload/UploadButton';
 import bs58 from 'bs58';
 import AddPhotoAlternateOutlined from '@mui/icons-material/AddPhotoAlternateOutlined';
 import ComlinkCryptoWorker from '@ente/shared/crypto';
-import { UploadTypeSelectorIntent } from 'types/gallery';
+import { SelectedState, UploadTypeSelectorIntent } from 'types/gallery';
 import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';
 import MoreHoriz from '@mui/icons-material/MoreHoriz';
 import OverflowMenu from '@ente/shared/components/OverflowMenu/menu';
@@ -60,6 +66,7 @@ import { OverflowMenuOption } from '@ente/shared/components/OverflowMenu/option'
 import { ENTE_WEBSITE_LINK } from '@ente/shared/constants/urls';
 import { APPS } from '@ente/shared/apps/constants';
 import downloadManager from 'services/download';
+import SelectedFileOptions from 'components/pages/sharedAlbum/SelectedFileOptions';
 
 export default function PublicCollectionGallery() {
     const token = useRef<string>(null);
@@ -87,6 +94,12 @@ export default function PublicCollectionGallery() {
     const [blockingLoad, setBlockingLoad] = useState(false);
     const [shouldDisableDropzone, setShouldDisableDropzone] = useState(false);
 
+    const [selected, setSelected] = useState<SelectedState>({
+        ownCount: 0,
+        count: 0,
+        collectionID: 0,
+    });
+
     const {
         getRootProps: getDragAndDropRootProps,
         getInputProps: getDragAndDropInputProps,
@@ -441,6 +454,22 @@ export default function PublicCollectionGallery() {
         }
     }
 
+    const downloadFilesHelper = async () => {
+        try {
+            const selectedFiles = getSelectedFiles(selected, publicFiles);
+            await downloadFiles(selectedFiles);
+        } catch (e) {
+            logError(e, 'failed to download selected files');
+        }
+    };
+
+    const clearSelection = () => {
+        if (!selected?.count) {
+            return;
+        }
+        setSelected({ ownCount: 0, count: 0, collectionID: 0 });
+    };
+
     return (
         <PublicCollectionGalleryContext.Provider
             value={{
@@ -468,8 +497,8 @@ export default function PublicCollectionGallery() {
                     page={PAGES.SHARED_ALBUMS}
                     files={publicFiles}
                     syncWithRemote={syncWithRemote}
-                    setSelected={() => null}
-                    selected={{ count: 0, collectionID: null, ownCount: 0 }}
+                    setSelected={setSelected}
+                    selected={selected}
                     activeCollectionID={ALL_SECTION}
                     enableDownload={downloadEnabled}
                     fileToCollectionsMap={null}
@@ -498,6 +527,14 @@ export default function PublicCollectionGallery() {
                         UploadTypeSelectorIntent.collectPhotos
                     }
                 />
+                {selected.count > 0 && (
+                    <SelectedFileOptions
+                        downloadFilesHelper={downloadFilesHelper}
+                        clearSelection={clearSelection}
+                        count={selected.count}
+                        ownCount={selected.ownCount}
+                    />
+                )}
             </FullScreenDropZone>
         </PublicCollectionGalleryContext.Provider>
     );