ente/src/pages/gallery/index.tsx

743 lines
27 KiB
TypeScript
Raw Normal View History

2021-08-11 07:35:40 +00:00
import React, {
createContext,
useContext,
useEffect,
useRef,
useState,
} from 'react';
2021-05-30 16:56:48 +00:00
import { useRouter } from 'next/router';
import { clearKeys, getKey, SESSION_KEYS } from 'utils/storage/sessionStorage';
import {
File,
getLocalFiles,
syncFiles,
2021-09-21 10:38:03 +00:00
updateMagicMetadata,
2021-09-22 08:28:23 +00:00
VISIBILITY_STATE,
2021-09-28 07:09:59 +00:00
trashFiles,
deleteFromTrash,
} from 'services/fileService';
2020-09-20 15:18:35 +00:00
import styled from 'styled-components';
2021-02-08 17:15:13 +00:00
import LoadingBar from 'react-top-loading-bar';
import {
Collection,
2021-02-08 16:15:21 +00:00
syncCollections,
CollectionAndItsLatestFile,
getCollectionsAndTheirLatestFile,
getFavItemIds,
2021-02-08 17:15:13 +00:00
getLocalCollections,
2021-03-15 17:30:49 +00:00
getNonEmptyCollections,
2021-09-28 08:03:32 +00:00
createCollection,
CollectionType,
} from 'services/collectionService';
2021-01-24 20:59:58 +00:00
import constants from 'utils/strings/constants';
import billingService from 'services/billingService';
2021-05-30 16:56:48 +00:00
import { checkSubscriptionPurchase } from 'utils/billingUtil';
2020-09-20 15:18:35 +00:00
import FullScreenDropZone from 'components/FullScreenDropZone';
import Sidebar from 'components/Sidebar';
2021-05-30 16:56:48 +00:00
import { checkConnectivity } from 'utils/common';
2021-04-22 14:30:07 +00:00
import {
isFirstLogin,
justSignedUp,
setIsFirstLogin,
setJustSignedUp,
} from 'utils/storage';
2021-05-30 16:56:48 +00:00
import { isTokenValid, logoutUser } from 'services/userService';
import MessageDialog, { MessageAttributes } from 'components/MessageDialog';
import { useDropzone } from 'react-dropzone';
import EnteSpinner from 'components/EnteSpinner';
2021-05-30 16:56:48 +00:00
import { LoadingOverlay } from 'components/LoadingOverlay';
2021-05-29 06:27:52 +00:00
import PhotoFrame from 'components/PhotoFrame';
2021-09-21 10:38:03 +00:00
import {
2021-09-22 08:28:23 +00:00
changeFilesVisibility,
2021-11-27 07:53:05 +00:00
downloadFiles,
getNonTrashedUniqueUserFiles,
2021-09-28 07:09:59 +00:00
getSelectedFiles,
2021-10-29 12:40:02 +00:00
mergeMetadata,
sortFiles,
2021-09-21 10:38:03 +00:00
sortFilesIntoCollections,
} from 'utils/file';
2021-05-30 16:56:48 +00:00
import SearchBar, { DateValue } from 'components/SearchBar';
import { Bbox } from 'services/searchService';
import SelectedFileOptions from 'components/pages/gallery/SelectedFileOptions';
import CollectionSelector, {
CollectionSelectorAttributes,
} from 'components/pages/gallery/CollectionSelector';
2021-05-29 06:27:52 +00:00
import CollectionNamer, {
CollectionNamerAttributes,
} from 'components/pages/gallery/CollectionNamer';
import AlertBanner from 'components/pages/gallery/AlertBanner';
import UploadButton from 'components/pages/gallery/UploadButton';
import PlanSelector from 'components/pages/gallery/PlanSelector';
import Upload from 'components/pages/gallery/Upload';
2021-09-30 06:39:28 +00:00
import Collections, {
ALL_SECTION,
ARCHIVE_SECTION,
TRASH_SECTION,
2021-09-30 06:39:28 +00:00
} from 'components/pages/gallery/Collections';
2021-06-04 07:57:48 +00:00
import { AppContext } from 'pages/_app';
import { CustomError, ServerErrorCodes } from 'utils/common/errorUtil';
import { PAGES } from 'types';
import {
COLLECTION_OPS_TYPE,
isSharedCollection,
2021-09-28 08:03:32 +00:00
handleCollectionOps,
2021-09-28 08:14:45 +00:00
getSelectedCollection,
2021-09-30 07:55:49 +00:00
isFavoriteCollection,
} from 'utils/collection';
import { logError } from 'utils/sentry';
import {
clearLocalTrash,
2021-10-26 07:35:12 +00:00
emptyTrash,
getLocalTrash,
getTrashedFiles,
syncTrash,
Trash,
} from 'services/trashService';
2021-10-26 07:35:12 +00:00
import DeleteBtn from 'components/DeleteBtn';
import FixCreationTime, {
FixCreationTimeAttributes,
} from 'components/FixCreationTime';
2021-04-19 08:29:12 +00:00
export const DeadCenter = styled.div`
flex: 1;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
flex-direction: column;
2020-11-28 18:11:24 +00:00
`;
2021-05-27 08:27:32 +00:00
const AlertContainer = styled.div`
background-color: #111;
padding: 5px 0;
font-size: 14px;
text-align: center;
`;
2020-11-28 18:11:24 +00:00
export type SelectedState = {
[k: number]: boolean;
2021-03-20 14:58:12 +00:00
count: number;
collectionID: number;
};
2021-05-18 14:20:38 +00:00
export type SetFiles = React.Dispatch<React.SetStateAction<File[]>>;
export type SetCollections = React.Dispatch<React.SetStateAction<Collection[]>>;
export type SetLoading = React.Dispatch<React.SetStateAction<Boolean>>;
2021-05-27 08:27:32 +00:00
export type setSearchStats = React.Dispatch<React.SetStateAction<SearchStats>>;
2021-05-26 20:36:02 +00:00
export type Search = {
2021-05-28 16:25:19 +00:00
date?: DateValue;
2021-05-26 20:36:02 +00:00
location?: Bbox;
2021-10-06 05:54:05 +00:00
fileIndex?: number;
2021-05-27 08:27:32 +00:00
};
export interface SearchStats {
resultCount: number;
timeTaken: number;
2021-05-26 20:36:02 +00:00
}
2021-03-20 14:58:12 +00:00
2021-05-30 16:35:12 +00:00
type GalleryContextType = {
thumbs: Map<number, string>;
files: Map<number, string>;
showPlanSelectorModal: () => void;
setActiveCollection: (collection: number) => void;
2021-10-29 12:11:59 +00:00
syncWithRemote: (force?: boolean, silent?: boolean) => Promise<void>;
2021-08-11 07:35:40 +00:00
};
2021-05-30 16:35:12 +00:00
const defaultGalleryContext: GalleryContextType = {
thumbs: new Map(),
files: new Map(),
showPlanSelectorModal: () => null,
setActiveCollection: () => null,
2021-10-29 12:11:59 +00:00
syncWithRemote: () => null,
2021-05-30 16:35:12 +00:00
};
2021-08-11 07:35:40 +00:00
export const GalleryContext = createContext<GalleryContextType>(
2021-08-13 02:38:38 +00:00
defaultGalleryContext
2021-08-11 07:35:40 +00:00
);
2021-05-30 16:35:12 +00:00
export default function Gallery() {
const router = useRouter();
const [collections, setCollections] = useState<Collection[]>([]);
2021-08-11 07:35:40 +00:00
const [collectionsAndTheirLatestFile, setCollectionsAndTheirLatestFile] =
useState<CollectionAndItsLatestFile[]>([]);
const [files, setFiles] = useState<File[]>(null);
2021-01-20 12:05:04 +00:00
const [favItemIds, setFavItemIds] = useState<Set<number>>();
2021-09-13 03:43:34 +00:00
const [bannerMessage, setBannerMessage] = useState<JSX.Element | string>(
null
);
const [isFirstLoad, setIsFirstLoad] = useState(false);
2021-05-26 16:48:29 +00:00
const [isFirstFetch, setIsFirstFetch] = useState(false);
const [selected, setSelected] = useState<SelectedState>({
count: 0,
collectionID: 0,
});
const [dialogMessage, setDialogMessage] = useState<MessageAttributes>();
const [dialogView, setDialogView] = useState(false);
2021-08-01 11:31:07 +00:00
const [planModalView, setPlanModalView] = useState(false);
const [loading, setLoading] = useState(false);
2021-08-11 07:35:40 +00:00
const [collectionSelectorAttributes, setCollectionSelectorAttributes] =
useState<CollectionSelectorAttributes>(null);
2021-04-27 05:35:49 +00:00
const [collectionSelectorView, setCollectionSelectorView] = useState(false);
2021-08-11 07:35:40 +00:00
const [collectionNamerAttributes, setCollectionNamerAttributes] =
useState<CollectionNamerAttributes>(null);
2021-04-27 05:35:49 +00:00
const [collectionNamerView, setCollectionNamerView] = useState(false);
2021-05-26 20:36:02 +00:00
const [search, setSearch] = useState<Search>({
date: null,
location: null,
2021-10-06 05:54:05 +00:00
fileIndex: null,
2021-05-26 20:36:02 +00:00
});
const [uploadInProgress, setUploadInProgress] = useState(false);
2021-04-27 05:35:49 +00:00
const {
getRootProps,
getInputProps,
open: openFileUploader,
acceptedFiles,
2021-07-24 14:55:12 +00:00
fileRejections,
2021-04-27 05:35:49 +00:00
} = useDropzone({
noClick: true,
noKeyboard: true,
disabled: uploadInProgress,
2021-04-27 05:35:49 +00:00
});
2021-02-17 08:35:19 +00:00
const loadingBar = useRef(null);
const [isInSearchMode, setIsInSearchMode] = useState(false);
2021-05-27 08:27:32 +00:00
const [searchStats, setSearchStats] = useState(null);
const syncInProgress = useRef(true);
2021-07-21 08:47:21 +00:00
const resync = useRef(false);
const [deleted, setDeleted] = useState<number[]>([]);
2021-06-04 07:57:48 +00:00
const appContext = useContext(AppContext);
2021-08-11 07:35:40 +00:00
const [collectionFilesCount, setCollectionFilesCount] =
useState<Map<number, number>>();
const [activeCollection, setActiveCollection] = useState<number>(undefined);
const [trash, setTrash] = useState<Trash>([]);
const [fixCreationTimeView, setFixCreationTimeView] = useState(false);
const [fixCreationTimeAttributes, setFixCreationTimeAttributes] =
useState<FixCreationTimeAttributes>(null);
2021-11-23 04:10:19 +00:00
useEffect(() => {
const key = getKey(SESSION_KEYS.ENCRYPTION_KEY);
if (!key) {
appContext.setRedirectUrl(router.asPath);
router.push(PAGES.ROOT);
2021-02-17 09:16:20 +00:00
return;
}
const main = async () => {
setActiveCollection(ALL_SECTION);
setIsFirstLoad(isFirstLogin());
2021-05-26 17:17:12 +00:00
setIsFirstFetch(true);
if (justSignedUp()) {
2021-04-20 09:30:45 +00:00
setPlanModalView(true);
}
setIsFirstLogin(false);
const files = mergeMetadata(await getLocalFiles());
const collections = await getLocalCollections();
const trash = await getLocalTrash();
const trashedFile = getTrashedFiles(trash);
setFiles(sortFiles([...files, ...trashedFile]));
setCollections(collections);
setTrash(trash);
await setDerivativeState(collections, files);
2021-06-06 20:26:31 +00:00
await syncWithRemote(true);
setIsFirstLoad(false);
2021-04-22 14:30:07 +00:00
setJustSignedUp(false);
2021-05-26 16:48:29 +00:00
setIsFirstFetch(false);
};
main();
2021-06-04 07:57:48 +00:00
appContext.showNavBar(true);
}, []);
useEffect(() => setDialogView(true), [dialogMessage]);
useEffect(
() => collectionSelectorAttributes && setCollectionSelectorView(true),
[collectionSelectorAttributes]
);
useEffect(
() => collectionNamerAttributes && setCollectionNamerView(true),
[collectionNamerAttributes]
);
useEffect(
() => fixCreationTimeAttributes && setFixCreationTimeView(true),
[fixCreationTimeAttributes]
);
useEffect(() => {
2021-11-23 04:10:19 +00:00
if (typeof activeCollection === 'undefined') {
return;
}
let collectionURL = '';
2021-09-30 06:39:28 +00:00
if (activeCollection !== ALL_SECTION) {
collectionURL += '?collection=';
2021-09-30 06:39:28 +00:00
if (activeCollection === ARCHIVE_SECTION) {
collectionURL += constants.ARCHIVE;
} else if (activeCollection === TRASH_SECTION) {
collectionURL += constants.TRASH;
2021-09-30 06:39:28 +00:00
} else {
collectionURL += activeCollection;
2021-09-30 06:39:28 +00:00
}
}
const href = `/gallery${collectionURL}`;
router.push(href, undefined, { shallow: true });
}, [activeCollection]);
useEffect(() => {
2021-11-23 04:15:19 +00:00
const key = getKey(SESSION_KEYS.ENCRYPTION_KEY);
if (router.isReady && key) {
checkSubscriptionPurchase(setDialogMessage, router, setLoading);
}
}, [router.isReady]);
2021-08-11 07:35:40 +00:00
const syncWithRemote = async (force = false, silent = false) => {
2021-07-21 08:47:21 +00:00
if (syncInProgress.current && !force) {
2021-08-11 07:35:40 +00:00
resync.current = true;
return;
}
2021-08-11 07:35:40 +00:00
syncInProgress.current = true;
try {
checkConnectivity();
if (!(await isTokenValid())) {
throw new Error(ServerErrorCodes.SESSION_EXPIRED);
2021-05-24 13:11:08 +00:00
}
!silent && loadingBar.current?.continuousStart();
await billingService.syncSubscription();
const collections = await syncCollections();
setCollections(collections);
const files = await syncFiles(collections, setFiles);
await setDerivativeState(collections, files);
const trash = await syncTrash(collections, setFiles, files);
setTrash(trash);
} catch (e) {
switch (e.message) {
case ServerErrorCodes.SESSION_EXPIRED:
setBannerMessage(constants.SESSION_EXPIRED_MESSAGE);
setDialogMessage({
title: constants.SESSION_EXPIRED,
content: constants.SESSION_EXPIRED_MESSAGE,
staticBackdrop: true,
nonClosable: true,
proceed: {
text: constants.LOGIN,
action: logoutUser,
variant: 'success',
2021-08-11 07:35:40 +00:00
},
});
break;
case CustomError.KEY_MISSING:
clearKeys();
router.push(PAGES.CREDENTIALS);
break;
}
} finally {
!silent && loadingBar.current?.complete();
}
2021-08-11 07:35:40 +00:00
syncInProgress.current = false;
if (resync.current) {
2021-08-11 07:35:40 +00:00
resync.current = false;
syncWithRemote();
}
2021-02-08 17:15:13 +00:00
};
const setDerivativeState = async (
collections: Collection[],
files: File[]
) => {
2021-10-29 12:40:02 +00:00
const favItemIds = await getFavItemIds(files);
setFavItemIds(favItemIds);
const nonEmptyCollections = getNonEmptyCollections(collections, files);
2021-10-29 12:40:02 +00:00
setCollections(nonEmptyCollections);
const collectionsAndTheirLatestFile = getCollectionsAndTheirLatestFile(
nonEmptyCollections,
files
);
2021-10-29 12:40:02 +00:00
setCollectionsAndTheirLatestFile(collectionsAndTheirLatestFile);
const collectionWiseFiles = sortFilesIntoCollections(files);
const collectionFilesCount = new Map<number, number>();
for (const [id, files] of collectionWiseFiles) {
collectionFilesCount.set(id, files.length);
}
setCollectionFilesCount(collectionFilesCount);
};
const clearSelection = function () {
setSelected({ count: 0, collectionID: 0 });
2021-04-22 12:56:06 +00:00
};
2021-03-20 14:58:12 +00:00
if (!files) {
return <div />;
}
2021-09-28 08:03:32 +00:00
const collectionOpsHelper =
(ops: COLLECTION_OPS_TYPE) => async (collection: Collection) => {
loadingBar.current?.continuousStart();
try {
await handleCollectionOps(
ops,
setCollectionSelectorView,
selected,
files,
setActiveCollection,
collection
);
clearSelection();
2021-09-28 08:03:32 +00:00
} catch (e) {
logError(e, 'collection ops failed', { ops });
2021-09-28 08:03:32 +00:00
setDialogMessage({
title: constants.ERROR,
staticBackdrop: true,
close: { variant: 'danger' },
content: constants.UNKNOWN_ERROR,
});
} finally {
await syncWithRemote(false, true);
loadingBar.current.complete();
2021-09-28 08:03:32 +00:00
}
};
2021-09-22 12:21:52 +00:00
const changeFilesVisibilityHelper = async (
visibility: VISIBILITY_STATE
) => {
2021-09-22 08:28:23 +00:00
loadingBar.current?.continuousStart();
try {
2021-09-22 12:21:52 +00:00
const updatedFiles = await changeFilesVisibility(
2021-09-22 08:28:23 +00:00
files,
selected,
2021-09-22 12:21:52 +00:00
visibility
2021-09-22 08:28:23 +00:00
);
2021-09-22 12:21:52 +00:00
await updateMagicMetadata(updatedFiles);
clearSelection();
2021-09-10 04:04:38 +00:00
} catch (e) {
logError(e, 'change file visibility failed');
2021-09-22 08:28:23 +00:00
switch (e.status?.toString()) {
case ServerErrorCodes.FORBIDDEN:
setDialogMessage({
title: constants.ERROR,
staticBackdrop: true,
close: { variant: 'danger' },
content: constants.NOT_FILE_OWNER,
});
return;
}
2021-09-10 04:04:38 +00:00
setDialogMessage({
title: constants.ERROR,
staticBackdrop: true,
close: { variant: 'danger' },
content: constants.UNKNOWN_ERROR,
});
2021-09-22 08:28:23 +00:00
} finally {
await syncWithRemote(false, true);
2021-09-22 08:28:23 +00:00
loadingBar.current.complete();
2021-09-10 04:04:38 +00:00
}
2021-05-07 09:37:12 +00:00
};
2021-09-28 08:03:32 +00:00
const showCreateCollectionModal = (ops: COLLECTION_OPS_TYPE) => {
const callback = async (collectionName: string) => {
try {
const collection = await createCollection(
collectionName,
CollectionType.album,
collections
);
await collectionOpsHelper(ops)(collection);
} catch (e) {
logError(e, 'create and collection ops failed');
setDialogMessage({
title: constants.ERROR,
staticBackdrop: true,
close: { variant: 'danger' },
content: constants.UNKNOWN_ERROR,
});
2021-09-28 08:03:32 +00:00
}
};
return () =>
setCollectionNamerAttributes({
title: constants.CREATE_COLLECTION,
buttonText: constants.CREATE,
autoFilledName: '',
callback,
});
};
const deleteFileHelper = async (permanent?: boolean) => {
2021-05-07 12:11:20 +00:00
loadingBar.current?.continuousStart();
2021-05-31 10:58:33 +00:00
try {
2021-09-28 07:09:59 +00:00
const selectedFiles = getSelectedFiles(selected, files);
if (permanent) {
await deleteFromTrash(selectedFiles.map((file) => file.id));
setDeleted([
...deleted,
...selectedFiles.map((file) => file.id),
]);
} else {
await trashFiles(selectedFiles);
}
clearSelection();
2021-05-31 10:58:33 +00:00
} catch (e) {
switch (e.status?.toString()) {
case ServerErrorCodes.FORBIDDEN:
2021-06-03 08:46:54 +00:00
setDialogMessage({
title: constants.ERROR,
staticBackdrop: true,
close: { variant: 'danger' },
content: constants.NOT_FILE_OWNER,
});
2021-05-31 10:58:33 +00:00
}
setDialogMessage({
title: constants.ERROR,
staticBackdrop: true,
close: { variant: 'danger' },
content: constants.UNKNOWN_ERROR,
});
} finally {
await syncWithRemote(false, true);
loadingBar.current.complete();
2021-05-31 10:58:33 +00:00
}
2021-05-07 09:37:12 +00:00
};
2021-05-26 20:36:02 +00:00
const updateSearch = (newSearch: Search) => {
2021-10-07 15:10:41 +00:00
setActiveCollection(ALL_SECTION);
setSearch(newSearch);
2021-05-27 08:27:32 +00:00
setSearchStats(null);
};
2021-06-06 20:26:31 +00:00
const closeCollectionSelector = (closeBtnClick?: boolean) => {
if (closeBtnClick === true) {
appContext.resetSharedFiles();
2021-06-06 20:26:31 +00:00
}
setCollectionSelectorView(false);
};
2021-10-26 07:35:12 +00:00
const emptyTrashHandler = () =>
setDialogMessage({
title: constants.CONFIRM_EMPTY_TRASH,
content: constants.EMPTY_TRASH_MESSAGE,
staticBackdrop: true,
proceed: {
action: emptyTrashHelper,
text: constants.EMPTY_TRASH,
variant: 'danger',
},
close: { text: constants.CANCEL },
});
const emptyTrashHelper = async () => {
loadingBar.current?.continuousStart();
try {
await emptyTrash();
if (selected.collectionID === TRASH_SECTION) {
clearSelection();
}
await clearLocalTrash();
setActiveCollection(ALL_SECTION);
2021-10-26 07:35:12 +00:00
} catch (e) {
setDialogMessage({
title: constants.ERROR,
staticBackdrop: true,
close: { variant: 'danger' },
content: constants.UNKNOWN_ERROR,
});
} finally {
await syncWithRemote(false, true);
loadingBar.current.complete();
}
};
const fixTimeHelper = async () => {
const selectedFiles = getSelectedFiles(selected, files);
setFixCreationTimeAttributes({ files: selectedFiles });
clearSelection();
};
2021-11-27 07:53:05 +00:00
const downloadHelper = async () => {
const selectedFiles = getSelectedFiles(selected, files);
clearSelection();
2021-11-27 10:10:15 +00:00
loadingBar.current?.continuousStart();
await downloadFiles(selectedFiles);
loadingBar.current.complete();
2021-11-27 07:53:05 +00:00
};
return (
<GalleryContext.Provider
value={{
...defaultGalleryContext,
showPlanSelectorModal: () => setPlanModalView(true),
setActiveCollection,
2021-10-29 12:11:59 +00:00
syncWithRemote,
}}>
2021-05-30 16:35:12 +00:00
<FullScreenDropZone
getRootProps={getRootProps}
getInputProps={getInputProps}>
2021-05-30 16:35:12 +00:00
{loading && (
<LoadingOverlay>
<EnteSpinner />
</LoadingOverlay>
)}
2021-08-27 08:52:04 +00:00
<LoadingBar color="#51cd7c" ref={loadingBar} />
2021-05-30 16:35:12 +00:00
{isFirstLoad && (
<AlertContainer>
{constants.INITIAL_LOAD_DELAY_WARNING}
</AlertContainer>
)}
2021-05-30 16:35:12 +00:00
<PlanSelector
modalView={planModalView}
closeModal={() => setPlanModalView(false)}
setDialogMessage={setDialogMessage}
setLoading={setLoading}
/>
<AlertBanner bannerMessage={bannerMessage} />
<MessageDialog
size="lg"
show={dialogView}
onHide={() => setDialogView(false)}
attributes={dialogMessage}
/>
<SearchBar
isOpen={isInSearchMode}
setOpen={setIsInSearchMode}
2021-05-30 16:35:12 +00:00
loadingBar={loadingBar}
isFirstFetch={isFirstFetch}
2021-09-22 18:51:55 +00:00
collections={collections}
files={getNonTrashedUniqueUserFiles(files)}
2021-09-22 18:51:55 +00:00
setActiveCollection={setActiveCollection}
2021-05-30 16:35:12 +00:00
setSearch={updateSearch}
searchStats={searchStats}
/>
<Collections
collections={collections}
collectionAndTheirLatestFile={collectionsAndTheirLatestFile}
isInSearchMode={isInSearchMode}
2021-09-22 06:03:07 +00:00
activeCollection={activeCollection}
setActiveCollection={setActiveCollection}
2021-05-30 16:35:12 +00:00
syncWithRemote={syncWithRemote}
setDialogMessage={setDialogMessage}
2021-05-30 16:35:12 +00:00
setCollectionNamerAttributes={setCollectionNamerAttributes}
startLoadingBar={loadingBar.current?.continuousStart}
2021-07-16 13:38:42 +00:00
collectionFilesCount={collectionFilesCount}
2021-05-30 16:35:12 +00:00
/>
<CollectionNamer
show={collectionNamerView}
onHide={setCollectionNamerView.bind(null, false)}
attributes={collectionNamerAttributes}
/>
<CollectionSelector
show={collectionSelectorView}
2021-06-06 20:26:31 +00:00
onHide={closeCollectionSelector}
2021-08-11 07:35:40 +00:00
collectionsAndTheirLatestFile={
collectionsAndTheirLatestFile
}
2021-05-30 16:35:12 +00:00
attributes={collectionSelectorAttributes}
/>
<FixCreationTime
isOpen={fixCreationTimeView}
hide={() => setFixCreationTimeView(false)}
show={() => setFixCreationTimeView(true)}
attributes={fixCreationTimeAttributes}
/>
2021-05-30 16:35:12 +00:00
<Upload
syncWithRemote={syncWithRemote}
setBannerMessage={setBannerMessage}
acceptedFiles={acceptedFiles}
2021-08-11 07:35:40 +00:00
showCollectionSelector={setCollectionSelectorView.bind(
null,
2021-08-13 02:38:38 +00:00
true
2021-08-11 07:35:40 +00:00
)}
setCollectionSelectorAttributes={
setCollectionSelectorAttributes
}
2021-05-30 16:35:12 +00:00
closeCollectionSelector={setCollectionSelectorView.bind(
null,
2021-08-13 02:38:38 +00:00
false
2021-05-30 16:35:12 +00:00
)}
setLoading={setLoading}
setCollectionNamerAttributes={setCollectionNamerAttributes}
setDialogMessage={setDialogMessage}
setUploadInProgress={setUploadInProgress}
2021-07-24 14:55:12 +00:00
fileRejections={fileRejections}
2021-07-25 07:56:05 +00:00
setFiles={setFiles}
2021-09-12 08:36:16 +00:00
isFirstUpload={collectionsAndTheirLatestFile?.length === 0}
2021-05-30 16:35:12 +00:00
/>
<Sidebar
collections={collections}
setDialogMessage={setDialogMessage}
2021-06-24 08:32:29 +00:00
setLoading={setLoading}
/>
2021-08-11 07:35:40 +00:00
<UploadButton
isFirstFetch={isFirstFetch}
openFileUploader={openFileUploader}
/>
2021-05-30 16:35:12 +00:00
<PhotoFrame
files={files}
setFiles={setFiles}
syncWithRemote={syncWithRemote}
favItemIds={favItemIds}
setSelected={setSelected}
selected={selected}
isFirstLoad={isFirstLoad}
openFileUploader={openFileUploader}
loadingBar={loadingBar}
isInSearchMode={isInSearchMode}
2021-05-30 16:35:12 +00:00
search={search}
setSearchStats={setSearchStats}
deleted={deleted}
setDialogMessage={setDialogMessage}
activeCollection={activeCollection}
isSharedCollection={isSharedCollection(
activeCollection,
collections
)}
2021-05-30 16:35:12 +00:00
/>
{selected.count > 0 &&
selected.collectionID === activeCollection && (
<SelectedFileOptions
2021-09-28 08:03:32 +00:00
addToCollectionHelper={collectionOpsHelper(
COLLECTION_OPS_TYPE.ADD
)}
2021-09-22 12:21:52 +00:00
archiveFilesHelper={() =>
changeFilesVisibilityHelper(
VISIBILITY_STATE.ARCHIVED
)
}
unArchiveFilesHelper={() =>
changeFilesVisibilityHelper(
VISIBILITY_STATE.VISIBLE
)
}
2021-09-28 08:03:32 +00:00
moveToCollectionHelper={collectionOpsHelper(
2021-09-28 08:40:14 +00:00
COLLECTION_OPS_TYPE.MOVE
2021-09-28 08:03:32 +00:00
)}
2021-10-04 07:01:05 +00:00
restoreToCollectionHelper={collectionOpsHelper(
COLLECTION_OPS_TYPE.RESTORE
)}
showCreateCollectionModal={
showCreateCollectionModal
}
setDialogMessage={setDialogMessage}
setCollectionSelectorAttributes={
setCollectionSelectorAttributes
}
deleteFileHelper={deleteFileHelper}
2021-09-28 08:14:45 +00:00
removeFromCollectionHelper={() =>
collectionOpsHelper(COLLECTION_OPS_TYPE.REMOVE)(
getSelectedCollection(
activeCollection,
collections
)
)
}
fixTimeHelper={fixTimeHelper}
2021-11-27 07:53:05 +00:00
downloadHelper={downloadHelper}
count={selected.count}
clearSelection={clearSelection}
2021-09-20 13:14:05 +00:00
activeCollection={activeCollection}
isFavoriteCollection={isFavoriteCollection(
activeCollection,
collections
)}
/>
)}
{activeCollection === TRASH_SECTION && trash?.length > 0 && (
2021-10-26 07:35:12 +00:00
<DeleteBtn onClick={emptyTrashHandler} />
)}
2021-05-30 16:35:12 +00:00
</FullScreenDropZone>
</GalleryContext.Provider>
);
}