added Archive logic
This commit is contained in:
parent
3021fd4a43
commit
ea6a2165e2
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue