added Archive logic

This commit is contained in:
abhinav-grd 2021-09-21 16:08:03 +05:30
parent 3021fd4a43
commit ea6a2165e2
3 changed files with 81 additions and 3 deletions

View file

@ -8,6 +8,7 @@ import CrossIcon from 'components/icons/CrossIcon';
import AddIcon from 'components/icons/AddIcon'; import AddIcon from 'components/icons/AddIcon';
import { IconButton } from 'components/Container'; import { IconButton } from 'components/Container';
import constants from 'utils/strings/constants'; import constants from 'utils/strings/constants';
import Archive from 'components/icons/archive';
interface Props { interface Props {
addToCollectionHelper: (collectionName, collection) => void; addToCollectionHelper: (collectionName, collection) => void;
@ -17,6 +18,7 @@ interface Props {
deleteFileHelper: () => void; deleteFileHelper: () => void;
count: number; count: number;
clearSelection: () => void; clearSelection: () => void;
archiveFilesHelper: () => void;
} }
const SelectionBar = styled(Navbar)` const SelectionBar = styled(Navbar)`
@ -41,6 +43,7 @@ const SelectedFileOptions = ({
deleteFileHelper, deleteFileHelper,
count, count,
clearSelection, clearSelection,
archiveFilesHelper,
}: Props) => { }: Props) => {
const addToCollection = () => const addToCollection = () =>
setCollectionSelectorAttributes({ setCollectionSelectorAttributes({
@ -72,6 +75,9 @@ const SelectedFileOptions = ({
{count} {constants.SELECTED} {count} {constants.SELECTED}
</div> </div>
</SelectionContainer> </SelectionContainer>
<IconButton onClick={archiveFilesHelper}>
<Archive />
</IconButton>
<IconButton onClick={addToCollection}> <IconButton onClick={addToCollection}>
<AddIcon /> <AddIcon />
</IconButton> </IconButton>

View file

@ -12,6 +12,7 @@ import {
getLocalFiles, getLocalFiles,
deleteFiles, deleteFiles,
syncFiles, syncFiles,
updateMagicMetadata,
} from 'services/fileService'; } from 'services/fileService';
import styled from 'styled-components'; import styled from 'styled-components';
import LoadingBar from 'react-top-loading-bar'; import LoadingBar from 'react-top-loading-bar';
@ -44,7 +45,11 @@ import { useDropzone } from 'react-dropzone';
import EnteSpinner from 'components/EnteSpinner'; import EnteSpinner from 'components/EnteSpinner';
import { LoadingOverlay } from 'components/LoadingOverlay'; import { LoadingOverlay } from 'components/LoadingOverlay';
import PhotoFrame from 'components/PhotoFrame'; import PhotoFrame from 'components/PhotoFrame';
import { getSelectedFileIds, sortFilesIntoCollections } from 'utils/file'; import {
archiveFiles,
getSelectedFileIds,
sortFilesIntoCollections,
} from 'utils/file';
import { addFilesToCollection } from 'utils/collection'; import { addFilesToCollection } from 'utils/collection';
import SearchBar, { DateValue } from 'components/SearchBar'; import SearchBar, { DateValue } from 'components/SearchBar';
import { Bbox } from 'services/searchService'; import { Bbox } from 'services/searchService';
@ -314,6 +319,36 @@ export default function Gallery() {
}); });
} }
}; };
const archiveFilesHelper = async () => {
loadingBar.current?.continuousStart();
try {
const archivedFiles = await archiveFiles(files, selected);
await updateMagicMetadata(archivedFiles);
setDeleted([...deleted, ...archivedFiles.map((file) => file.id)]);
} catch (e) {
console.log(e);
switch (e.status?.toString()) {
case ServerErrorCodes.FORBIDDEN:
setDialogMessage({
title: constants.ERROR,
staticBackdrop: true,
close: { variant: 'danger' },
content: constants.NOT_FILE_OWNER,
});
return;
}
setDialogMessage({
title: constants.ERROR,
staticBackdrop: true,
close: { variant: 'danger' },
content: constants.UNKNOWN_ERROR,
});
} finally {
clearSelection();
syncWithRemote();
loadingBar.current.complete();
}
};
const showCreateCollectionModal = () => const showCreateCollectionModal = () =>
setCollectionNamerAttributes({ setCollectionNamerAttributes({
@ -488,6 +523,7 @@ export default function Gallery() {
selected.collectionID === activeCollection && ( selected.collectionID === activeCollection && (
<SelectedFileOptions <SelectedFileOptions
addToCollectionHelper={addToCollectionHelper} addToCollectionHelper={addToCollectionHelper}
archiveFilesHelper={archiveFilesHelper}
showCreateCollectionModal={ showCreateCollectionModal={
showCreateCollectionModal showCreateCollectionModal
} }

View file

@ -1,13 +1,18 @@
import { SelectedState } from 'pages/gallery';
import { Collection } from 'services/collectionService'; import { Collection } from 'services/collectionService';
import { import {
File, File,
fileAttribute, fileAttribute,
FILE_TYPE, FILE_TYPE,
MagicMetadataProps,
NEW_MAGIC_METADATA,
VISIBILITY_STATE, VISIBILITY_STATE,
} from 'services/fileService'; } from 'services/fileService';
import { decodeMotionPhoto } from 'services/motionPhotoService'; import { decodeMotionPhoto } from 'services/motionPhotoService';
import { getMimeTypeFromBlob } from 'services/upload/readFileService'; import { getMimeTypeFromBlob } from 'services/upload/readFileService';
import { EncryptionResult } from 'services/upload/uploadService';
import CryptoWorker from 'utils/crypto'; import CryptoWorker from 'utils/crypto';
import { logError } from 'utils/sentry';
export const TYPE_HEIC = 'heic'; export const TYPE_HEIC = 'heic';
export const TYPE_HEIF = 'heif'; export const TYPE_HEIF = 'heif';
@ -47,7 +52,7 @@ export function sortFilesIntoCollections(files: File[]) {
return collectionWiseFiles; return collectionWiseFiles;
} }
export function getSelectedFileIds(selectedFiles) { export function getSelectedFileIds(selectedFiles: SelectedState) {
const filesIDs: number[] = []; const filesIDs: number[] = [];
for (const [key, val] of Object.entries(selectedFiles)) { for (const [key, val] of Object.entries(selectedFiles)) {
if (typeof val === 'boolean' && val) { if (typeof val === 'boolean' && val) {
@ -56,7 +61,10 @@ export function getSelectedFileIds(selectedFiles) {
} }
return filesIDs; return filesIDs;
} }
export function getSelectedFiles(selectedFiles, files: File[]): File[] { export function getSelectedFiles(
selectedFiles: SelectedState,
files: File[]
): File[] {
const filesIDs = new Set(getSelectedFileIds(selectedFiles)); const filesIDs = new Set(getSelectedFileIds(selectedFiles));
const filesToDelete: File[] = []; const filesToDelete: File[] = [];
for (const file of files) { for (const file of files) {
@ -213,3 +221,31 @@ export function fileIsArchived(file: File) {
} }
return file.magicMetadata.data.visibility === VISIBILITY_STATE.ARCHIVED; return file.magicMetadata.data.visibility === VISIBILITY_STATE.ARCHIVED;
} }
export async function archiveFiles(files: File[], selected: SelectedState) {
const worker = await new CryptoWorker();
const selectedFiles = getSelectedFiles(selected, files);
for (const file of selectedFiles) {
if (!file.magicMetadata) {
file.magicMetadata = NEW_MAGIC_METADATA;
}
if (typeof file.magicMetadata.data === 'string') {
logError(Error('magic metadata not decrypted'), '');
return;
}
const updatedMagicMetadataProps: MagicMetadataProps = {
...file.magicMetadata.data,
visibility: VISIBILITY_STATE.ARCHIVED,
};
const encryptedMagicMetadata: EncryptionResult =
await worker.encryptMetadata(updatedMagicMetadataProps);
file.magicMetadata = {
version: file.magicMetadata.version + 1,
count: Object.keys(updatedMagicMetadataProps).length,
data: encryptedMagicMetadata.file
.encryptedData as unknown as string,
header: encryptedMagicMetadata.file.decryptionHeader,
};
}
return selectedFiles;
}