2020-09-20 15:18:35 +00:00
|
|
|
import React, { useEffect, useState } from 'react';
|
2020-09-12 21:53:41 +00:00
|
|
|
import { useRouter } from 'next/router';
|
2020-09-19 21:20:10 +00:00
|
|
|
import Spinner from 'react-bootstrap/Spinner';
|
|
|
|
import { getKey, SESSION_KEYS } from 'utils/storage/sessionStorage';
|
2021-01-05 02:40:59 +00:00
|
|
|
import {
|
|
|
|
collection,
|
|
|
|
fetchCollections,
|
|
|
|
file,
|
2021-01-05 10:29:05 +00:00
|
|
|
getCollectionLatestFile,
|
2021-01-05 02:40:59 +00:00
|
|
|
getFile,
|
|
|
|
getFiles,
|
|
|
|
getPreview,
|
2021-01-05 10:29:05 +00:00
|
|
|
collectionLatestFile,
|
2021-01-05 02:40:59 +00:00
|
|
|
} from 'services/fileService';
|
2020-09-19 21:20:10 +00:00
|
|
|
import { getData, LS_KEYS } from 'utils/storage/localStorage';
|
|
|
|
import PreviewCard from './components/PreviewCard';
|
|
|
|
import { getActualKey } from 'utils/common/key';
|
2020-09-20 15:18:35 +00:00
|
|
|
import styled from 'styled-components';
|
2020-11-23 03:00:17 +00:00
|
|
|
import { PhotoSwipe } from 'react-photoswipe';
|
|
|
|
import { Options } from 'photoswipe';
|
2020-11-20 17:24:21 +00:00
|
|
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
2020-11-29 14:48:47 +00:00
|
|
|
import { VariableSizeList as List } from 'react-window';
|
2020-11-28 18:11:24 +00:00
|
|
|
import Collections from './components/Collections';
|
|
|
|
import SadFace from 'components/SadFace';
|
2021-01-05 02:40:59 +00:00
|
|
|
import FileUpload from './components/DragAndDropUpload';
|
2021-01-05 05:27:34 +00:00
|
|
|
import UploadButton from 'pages/gallery/components/UploadButton';
|
2021-01-05 07:35:47 +00:00
|
|
|
import CollectionSelector from './components/CollectionSelector';
|
2021-01-06 04:36:19 +00:00
|
|
|
import UploadProgress from './components/UploadProgress';
|
2020-09-20 15:18:35 +00:00
|
|
|
|
2020-11-29 14:48:47 +00:00
|
|
|
enum ITEM_TYPE {
|
2021-01-05 02:40:59 +00:00
|
|
|
TIME = 'TIME',
|
|
|
|
TILE = 'TILE',
|
2020-11-29 14:48:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
interface TimeStampListItem {
|
2021-01-05 02:40:59 +00:00
|
|
|
itemType: ITEM_TYPE;
|
|
|
|
items?: file[];
|
|
|
|
itemStartIndex?: number;
|
|
|
|
date?: string;
|
2020-11-29 14:48:47 +00:00
|
|
|
}
|
|
|
|
|
2020-09-20 15:18:35 +00:00
|
|
|
const Container = styled.div`
|
2021-01-05 02:40:59 +00:00
|
|
|
display: block;
|
|
|
|
flex: 1;
|
|
|
|
width: 100%;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
margin: 0 auto;
|
2020-09-20 15:18:35 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
.pswp-thumbnail {
|
|
|
|
display: inline-block;
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
2020-09-20 15:18:35 +00:00
|
|
|
`;
|
2020-09-12 21:53:41 +00:00
|
|
|
|
2020-11-20 17:24:21 +00:00
|
|
|
const ListItem = styled.div`
|
2021-01-05 02:40:59 +00:00
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
2020-11-28 18:11:24 +00:00
|
|
|
`;
|
|
|
|
|
|
|
|
const DeadCenter = styled.div`
|
2021-01-05 02:40:59 +00:00
|
|
|
flex: 1;
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
color: #fff;
|
|
|
|
text-align: center;
|
|
|
|
flex-direction: column;
|
2020-11-28 18:11:24 +00:00
|
|
|
`;
|
|
|
|
|
|
|
|
const ListContainer = styled.div`
|
2021-01-05 02:40:59 +00:00
|
|
|
display: flex;
|
|
|
|
max-width: 100%;
|
|
|
|
color: #fff;
|
2020-11-28 18:16:56 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
@media (min-width: 1000px) {
|
|
|
|
width: 1000px;
|
|
|
|
}
|
2020-11-28 18:11:24 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
@media (min-width: 450px) and (max-width: 1000px) {
|
|
|
|
width: 600px;
|
|
|
|
}
|
2020-11-28 18:11:24 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
@media (max-width: 450px) {
|
|
|
|
width: 100%;
|
|
|
|
}
|
2020-11-20 17:24:21 +00:00
|
|
|
`;
|
|
|
|
|
2020-11-29 14:55:07 +00:00
|
|
|
const DateContainer = styled.div`
|
2021-01-05 02:40:59 +00:00
|
|
|
padding: 0 4px;
|
2020-11-29 14:55:07 +00:00
|
|
|
`;
|
|
|
|
|
2020-11-07 15:43:00 +00:00
|
|
|
const PAGE_SIZE = 12;
|
|
|
|
const COLUMNS = 3;
|
|
|
|
|
2020-09-12 21:53:41 +00:00
|
|
|
export default function Gallery() {
|
2021-01-05 02:40:59 +00:00
|
|
|
const router = useRouter();
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const [collections, setCollections] = useState<collection[]>([]);
|
2021-01-05 10:29:05 +00:00
|
|
|
const [collectionLatestFile, setCollectionLatestFile] = useState<
|
|
|
|
collectionLatestFile[]
|
|
|
|
>([]);
|
2021-01-05 02:40:59 +00:00
|
|
|
const [data, setData] = useState<file[]>();
|
|
|
|
const [open, setOpen] = useState(false);
|
|
|
|
const [options, setOptions] = useState<Options>({
|
|
|
|
history: false,
|
|
|
|
maxSpreadZoom: 5,
|
|
|
|
});
|
|
|
|
const fetching: { [k: number]: boolean } = {};
|
2020-09-12 21:53:41 +00:00
|
|
|
|
2021-01-05 05:27:34 +00:00
|
|
|
const [modalView, setModalView] = useState(false);
|
|
|
|
|
|
|
|
const closeModal = () => setModalView(false);
|
|
|
|
const showModal = () => setModalView(true);
|
|
|
|
|
2021-01-05 11:12:38 +00:00
|
|
|
const [progressView, setProgressView] = useState(false);
|
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
useEffect(() => {
|
|
|
|
const key = getKey(SESSION_KEYS.ENCRYPTION_KEY);
|
|
|
|
const token = getData(LS_KEYS.USER).token;
|
|
|
|
if (!key) {
|
|
|
|
router.push('/');
|
2020-09-12 21:53:41 +00:00
|
|
|
}
|
2021-01-05 02:40:59 +00:00
|
|
|
const main = async () => {
|
|
|
|
setLoading(true);
|
|
|
|
const encryptionKey = await getActualKey();
|
|
|
|
const collections = await fetchCollections(token, encryptionKey);
|
|
|
|
const resp = await getFiles(
|
|
|
|
'0',
|
|
|
|
token,
|
|
|
|
'100',
|
|
|
|
encryptionKey,
|
|
|
|
collections
|
|
|
|
);
|
|
|
|
setLoading(false);
|
|
|
|
setCollections(collections);
|
|
|
|
setData(
|
|
|
|
resp.map((item) => ({
|
|
|
|
...item,
|
|
|
|
w: window.innerWidth,
|
|
|
|
h: window.innerHeight,
|
|
|
|
}))
|
|
|
|
);
|
2021-01-05 10:29:05 +00:00
|
|
|
const collectionLatestFile = await getCollectionLatestFile(
|
|
|
|
collections,
|
|
|
|
resp
|
|
|
|
);
|
|
|
|
setCollectionLatestFile(collectionLatestFile);
|
2021-01-05 02:40:59 +00:00
|
|
|
};
|
|
|
|
main();
|
|
|
|
}, []);
|
2020-09-12 21:53:41 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
if (!data || loading) {
|
|
|
|
return (
|
|
|
|
<div className='text-center'>
|
|
|
|
<Spinner animation='border' variant='primary' />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const updateUrl = (index: number) => (url: string) => {
|
|
|
|
data[index] = {
|
|
|
|
...data[index],
|
|
|
|
msrc: url,
|
|
|
|
w: window.innerWidth,
|
|
|
|
h: window.innerHeight,
|
|
|
|
};
|
|
|
|
if (data[index].metadata.fileType === 1 && !data[index].html) {
|
|
|
|
data[index].html = `
|
2020-11-26 15:57:20 +00:00
|
|
|
<div class="video-loading">
|
|
|
|
<img src="${url}" />
|
|
|
|
<div class="spinner-border text-light" role="status">
|
|
|
|
<span class="sr-only">Loading...</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
`;
|
2021-01-05 02:40:59 +00:00
|
|
|
delete data[index].src;
|
2020-11-24 04:40:02 +00:00
|
|
|
}
|
2021-01-05 02:40:59 +00:00
|
|
|
if (data[index].metadata.fileType === 0 && !data[index].src) {
|
|
|
|
data[index].src = url;
|
|
|
|
}
|
|
|
|
setData(data);
|
|
|
|
};
|
2020-11-24 04:40:02 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
const updateSrcUrl = (index: number, url: string) => {
|
|
|
|
data[index] = {
|
|
|
|
...data[index],
|
|
|
|
src: url,
|
|
|
|
w: window.innerWidth,
|
|
|
|
h: window.innerHeight,
|
|
|
|
};
|
|
|
|
if (data[index].metadata.fileType === 1) {
|
|
|
|
data[index].html = `
|
2020-11-26 15:57:20 +00:00
|
|
|
<video controls>
|
2020-11-26 17:35:26 +00:00
|
|
|
<source src="${url}" />
|
2020-11-26 15:57:20 +00:00
|
|
|
Your browser does not support the video tag.
|
|
|
|
</video>
|
|
|
|
`;
|
2021-01-05 02:40:59 +00:00
|
|
|
delete data[index].src;
|
2020-11-23 03:00:17 +00:00
|
|
|
}
|
2021-01-05 02:40:59 +00:00
|
|
|
setData(data);
|
|
|
|
};
|
2020-11-23 03:00:17 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
const handleClose = () => {
|
|
|
|
setOpen(false);
|
|
|
|
};
|
2020-11-23 03:00:17 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
const onThumbnailClick = (index: number) => () => {
|
|
|
|
setOptions({
|
|
|
|
...options,
|
|
|
|
index,
|
|
|
|
});
|
|
|
|
setOpen(true);
|
|
|
|
};
|
2020-11-23 03:00:17 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
const getThumbnail = (file: file[], index: number) => {
|
|
|
|
return (
|
|
|
|
<PreviewCard
|
|
|
|
key={`tile-${file[index].id}`}
|
|
|
|
data={file[index]}
|
|
|
|
updateUrl={updateUrl(file[index].dataIndex)}
|
|
|
|
onClick={onThumbnailClick(index)}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
};
|
2020-09-20 15:18:35 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
const getSlideData = async (instance: any, index: number, item: file) => {
|
|
|
|
const token = getData(LS_KEYS.USER).token;
|
|
|
|
if (!item.msrc) {
|
|
|
|
const url = await getPreview(token, item);
|
|
|
|
updateUrl(item.dataIndex)(url);
|
|
|
|
item.msrc = url;
|
|
|
|
if (!item.src) {
|
|
|
|
item.src = url;
|
|
|
|
}
|
|
|
|
item.w = window.innerWidth;
|
|
|
|
item.h = window.innerHeight;
|
|
|
|
try {
|
|
|
|
instance.invalidateCurrItems();
|
|
|
|
instance.updateSize(true);
|
|
|
|
} catch (e) {
|
|
|
|
// ignore
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((!item.src || item.src === item.msrc) && !fetching[item.dataIndex]) {
|
|
|
|
fetching[item.dataIndex] = true;
|
|
|
|
const url = await getFile(token, item);
|
|
|
|
updateSrcUrl(item.dataIndex, url);
|
|
|
|
if (item.metadata.fileType === 1) {
|
|
|
|
item.html = `
|
2020-11-26 15:57:20 +00:00
|
|
|
<video width="320" height="240" controls>
|
2020-11-26 17:35:26 +00:00
|
|
|
<source src="${url}" />
|
2020-11-26 15:57:20 +00:00
|
|
|
Your browser does not support the video tag.
|
|
|
|
</video>
|
|
|
|
`;
|
2021-01-05 02:40:59 +00:00
|
|
|
delete item.src;
|
|
|
|
item.w = window.innerWidth;
|
|
|
|
} else {
|
|
|
|
item.src = url;
|
|
|
|
}
|
|
|
|
item.h = window.innerHeight;
|
|
|
|
try {
|
|
|
|
instance.invalidateCurrItems();
|
|
|
|
instance.updateSize(true);
|
|
|
|
} catch (e) {
|
|
|
|
// ignore
|
|
|
|
}
|
2020-11-24 04:40:02 +00:00
|
|
|
}
|
2021-01-05 02:40:59 +00:00
|
|
|
};
|
2020-11-24 04:40:02 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
const selectCollection = (id?: string) => {
|
|
|
|
const href = `/gallery?collection=${id || ''}`;
|
|
|
|
router.push(href, undefined, { shallow: true });
|
|
|
|
};
|
2020-11-28 18:11:24 +00:00
|
|
|
|
2021-01-05 10:29:05 +00:00
|
|
|
let idSet = new Set();
|
2021-01-05 02:40:59 +00:00
|
|
|
const filteredData = data
|
|
|
|
.map((item, index) => ({
|
|
|
|
...item,
|
|
|
|
dataIndex: index,
|
|
|
|
}))
|
|
|
|
.filter((item) => {
|
|
|
|
if (!idSet.has(item.id)) {
|
|
|
|
if (
|
|
|
|
!router.query.collection ||
|
|
|
|
router.query.collection === item.collectionID.toString()
|
|
|
|
) {
|
|
|
|
idSet.add(item.id);
|
|
|
|
return true;
|
2020-11-28 18:11:24 +00:00
|
|
|
}
|
|
|
|
return false;
|
2021-01-05 02:40:59 +00:00
|
|
|
}
|
|
|
|
return false;
|
2020-11-28 18:11:24 +00:00
|
|
|
});
|
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
const isSameDay = (first, second) => {
|
|
|
|
return (
|
|
|
|
first.getFullYear() === second.getFullYear() &&
|
|
|
|
first.getMonth() === second.getMonth() &&
|
|
|
|
first.getDate() === second.getDate()
|
|
|
|
);
|
|
|
|
};
|
2020-11-29 14:48:47 +00:00
|
|
|
|
2021-01-05 02:40:59 +00:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Collections
|
|
|
|
collections={collections}
|
|
|
|
selected={router.query.collection?.toString()}
|
|
|
|
selectCollection={selectCollection}
|
|
|
|
/>
|
2021-01-05 07:35:47 +00:00
|
|
|
<UploadButton showModal={showModal} />
|
2021-01-05 11:12:38 +00:00
|
|
|
<FileUpload
|
|
|
|
noClick
|
|
|
|
closeModal={closeModal}
|
|
|
|
showModal={showModal}
|
|
|
|
>
|
2021-01-05 07:35:47 +00:00
|
|
|
<CollectionSelector
|
|
|
|
modalView={modalView}
|
|
|
|
closeModal={closeModal}
|
2021-01-05 10:29:05 +00:00
|
|
|
collectionLatestFile={collectionLatestFile}
|
2021-01-05 11:12:38 +00:00
|
|
|
showProgress={() => setProgressView(true)}
|
|
|
|
/>
|
|
|
|
<UploadProgress
|
|
|
|
show={progressView}
|
|
|
|
onHide={() => setProgressView(false)}
|
2021-01-05 07:35:47 +00:00
|
|
|
/>
|
2021-01-05 07:17:46 +00:00
|
|
|
{filteredData.length ? (
|
|
|
|
<Container>
|
|
|
|
<AutoSizer>
|
|
|
|
{({ height, width }) => {
|
|
|
|
let columns;
|
|
|
|
if (width >= 1000) {
|
|
|
|
columns = 5;
|
|
|
|
} else if (width < 1000 && width >= 450) {
|
|
|
|
columns = 3;
|
|
|
|
} else if (width < 450 && width >= 300) {
|
|
|
|
columns = 2;
|
2021-01-05 05:27:34 +00:00
|
|
|
} else {
|
2021-01-05 07:17:46 +00:00
|
|
|
columns = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const timeStampList: TimeStampListItem[] = [];
|
|
|
|
let listItemIndex = 0;
|
|
|
|
let currentDate = -1;
|
|
|
|
filteredData.forEach((item, index) => {
|
|
|
|
if (
|
|
|
|
!isSameDay(
|
|
|
|
new Date(item.metadata.creationTime / 1000),
|
|
|
|
new Date(currentDate)
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
currentDate = item.metadata.creationTime / 1000;
|
|
|
|
const dateTimeFormat = new Intl.DateTimeFormat('en-IN', {
|
|
|
|
weekday: 'short',
|
|
|
|
year: 'numeric',
|
|
|
|
month: 'long',
|
|
|
|
day: 'numeric',
|
|
|
|
});
|
|
|
|
timeStampList.push({
|
|
|
|
itemType: ITEM_TYPE.TIME,
|
|
|
|
date: dateTimeFormat.format(currentDate),
|
|
|
|
});
|
2021-01-05 02:40:59 +00:00
|
|
|
timeStampList.push({
|
|
|
|
itemType: ITEM_TYPE.TILE,
|
|
|
|
items: [item],
|
|
|
|
itemStartIndex: index,
|
|
|
|
});
|
2021-01-05 07:17:46 +00:00
|
|
|
listItemIndex = 1;
|
|
|
|
} else {
|
|
|
|
if (listItemIndex < columns) {
|
|
|
|
timeStampList[timeStampList.length - 1].items.push(item);
|
|
|
|
listItemIndex++;
|
|
|
|
} else {
|
|
|
|
listItemIndex = 1;
|
|
|
|
timeStampList.push({
|
|
|
|
itemType: ITEM_TYPE.TILE,
|
|
|
|
items: [item],
|
|
|
|
itemStartIndex: index,
|
|
|
|
});
|
|
|
|
}
|
2021-01-05 02:40:59 +00:00
|
|
|
}
|
2021-01-05 07:17:46 +00:00
|
|
|
});
|
2020-11-29 14:48:47 +00:00
|
|
|
|
2021-01-05 07:17:46 +00:00
|
|
|
return (
|
|
|
|
<List
|
|
|
|
itemSize={(index) =>
|
|
|
|
timeStampList[index].itemType === ITEM_TYPE.TIME
|
|
|
|
? 30
|
|
|
|
: 200
|
|
|
|
}
|
|
|
|
height={height}
|
|
|
|
width={width}
|
|
|
|
itemCount={timeStampList.length}
|
|
|
|
key={`${router.query.collection}-${columns}`}
|
|
|
|
>
|
|
|
|
{({ index, style }) => {
|
|
|
|
return (
|
|
|
|
<ListItem style={style}>
|
|
|
|
<ListContainer>
|
|
|
|
{timeStampList[index].itemType ===
|
2021-01-06 04:36:19 +00:00
|
|
|
ITEM_TYPE.TIME ? (
|
|
|
|
<DateContainer>
|
|
|
|
{timeStampList[index].date}
|
|
|
|
</DateContainer>
|
|
|
|
) : (
|
|
|
|
timeStampList[index].items.map((item, idx) => {
|
|
|
|
return getThumbnail(
|
|
|
|
filteredData,
|
|
|
|
timeStampList[index].itemStartIndex + idx
|
|
|
|
);
|
|
|
|
})
|
|
|
|
)}
|
2021-01-05 07:17:46 +00:00
|
|
|
</ListContainer>
|
|
|
|
</ListItem>
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
</List>
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
</AutoSizer>
|
|
|
|
<PhotoSwipe
|
|
|
|
isOpen={open}
|
|
|
|
items={filteredData}
|
|
|
|
options={options}
|
|
|
|
onClose={handleClose}
|
|
|
|
gettingData={getSlideData}
|
|
|
|
/>
|
|
|
|
</Container>
|
|
|
|
) : (
|
2021-01-06 04:36:19 +00:00
|
|
|
<DeadCenter>
|
|
|
|
<SadFace height={100} width={100} />
|
|
|
|
<div>No content found!</div>
|
|
|
|
</DeadCenter>
|
|
|
|
)}
|
2021-01-05 02:40:59 +00:00
|
|
|
</FileUpload>
|
|
|
|
</>
|
|
|
|
);
|
2020-09-12 21:53:41 +00:00
|
|
|
}
|