rendering file sizes and count

This commit is contained in:
Rushikesh Tote 2022-03-25 14:32:33 +05:30
parent b8e33fa13e
commit 7c047f2306
8 changed files with 134 additions and 30 deletions

View file

@ -18,7 +18,13 @@ import {
import { isSharedFile } from 'utils/file';
import { isPlaybackPossible } from 'utils/photoFrame';
import { PhotoList } from './PhotoList';
import { SetFiles, SelectedState, Search, setSearchStats } from 'types/gallery';
import {
SetFiles,
SelectedState,
Search,
setSearchStats,
DeduplicatingType,
} from 'types/gallery';
import { FILE_TYPE } from 'constants/file';
import PublicCollectionDownloadManager from 'services/publicCollectionDownloadManager';
import { PublicCollectionGalleryContext } from 'utils/publicCollectionGallery';
@ -70,6 +76,7 @@ interface Props {
activeCollection: number;
isSharedCollection: boolean;
enableDownload: boolean;
deduplicating?: DeduplicatingType;
}
type SourceURL = {
@ -93,6 +100,7 @@ const PhotoFrame = ({
activeCollection,
isSharedCollection,
enableDownload,
deduplicating,
}: Props) => {
const [open, setOpen] = useState(false);
const [currentIndex, setCurrentIndex] = useState<number>(0);
@ -580,6 +588,7 @@ const PhotoFrame = ({
files.length < 30 && !isInSearchMode
}
resetFetching={resetFetching}
deduplicating={deduplicating}
/>
)}
</AutoSizer>

View file

@ -9,11 +9,14 @@ import {
DATE_CONTAINER_HEIGHT,
GAP_BTW_TILES,
SPACE_BTW_DATES,
SIZE_AND_COUNT_CONTAINER_HEIGHT,
} from 'constants/gallery';
import constants from 'utils/strings/constants';
import { PublicCollectionGalleryContext } from 'utils/publicCollectionGallery';
import { ENTE_WEBSITE_LINK } from 'constants/urls';
import { getVariantColor, ButtonVariant } from './pages/gallery/LinkButton';
import { getReadableSizeFromBytes } from 'utils/photoList';
import { DeduplicatingType } from 'types/gallery';
const A_DAY = 24 * 60 * 60 * 1000;
const NO_OF_PAGES = 2;
@ -22,6 +25,7 @@ const FOOTER_HEIGHT = 90;
enum ITEM_TYPE {
TIME = 'TIME',
TILE = 'TILE',
SIZE_AND_CNT = 'SIZE_AND_CNT',
OTHER = 'OTHER',
}
@ -38,6 +42,8 @@ interface TimeStampListItem {
item?: any;
id?: string;
height?: number;
fileSize?: number;
fileCount?: number;
}
const ListItem = styled.div`
@ -85,6 +91,18 @@ const DateContainer = styled.div<{ span: number }>`
height: ${DATE_CONTAINER_HEIGHT}px;
`;
const SizeAndCountContainer = styled.div<{ span: number }>`
user-select: none;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
grid-column: span ${(props) => props.span};
display: flex;
align-items: center;
margin-top: 1rem;
height: ${SIZE_AND_COUNT_CONTAINER_HEIGHT}px;
`;
const FooterContainer = styled.div<{ span: number }>`
font-size: 14px;
margin-bottom: 0.75rem;
@ -122,6 +140,7 @@ interface Props {
getThumbnail: (files: EnteFile[], index: number) => JSX.Element;
activeCollection: number;
resetFetching: () => void;
deduplicating?: DeduplicatingType;
}
export function PhotoList({
@ -132,6 +151,7 @@ export function PhotoList({
getThumbnail,
activeCollection,
resetFetching,
deduplicating,
}: Props) {
const timeStampListRef = useRef([]);
const timeStampList = timeStampListRef?.current ?? [];
@ -158,6 +178,81 @@ export function PhotoList({
useEffect(() => {
let timeStampList: TimeStampListItem[] = [];
if (deduplicating) {
groupByFileSize(timeStampList);
} else {
groupByTime(timeStampList);
}
if (!skipMerge && !deduplicating) {
timeStampList = mergeTimeStampList(timeStampList, columns);
}
if (timeStampList.length === 0) {
timeStampList.push(getEmptyListItem());
}
if (
showAppDownloadBanner ||
publicCollectionGalleryContext.accessedThroughSharedURL
) {
timeStampList.push(getVacuumItem(timeStampList));
if (publicCollectionGalleryContext.accessedThroughSharedURL) {
timeStampList.push(getAlbumsFooter());
} else {
timeStampList.push(getAppDownloadFooter());
}
}
timeStampListRef.current = timeStampList;
filteredDataCopyRef.current = filteredData;
refreshList();
}, [
width,
height,
filteredData,
showAppDownloadBanner,
publicCollectionGalleryContext.accessedThroughSharedURL,
]);
const groupByFileSize = (timeStampList: TimeStampListItem[]) => {
let index = 0;
while (index < filteredData.length) {
const file = filteredData[index];
const currentFileSize = file.file.size;
const currentCreationTime = file.metadata.creationTime;
let lastFileIndex = index;
while (lastFileIndex < filteredData.length) {
if (
filteredData[lastFileIndex].file.size !== currentFileSize ||
(deduplicating.clubByTime &&
filteredData[lastFileIndex].metadata.creationTime !==
currentCreationTime)
) {
break;
}
lastFileIndex++;
}
lastFileIndex--;
timeStampList.push({
itemType: ITEM_TYPE.SIZE_AND_CNT,
fileSize: currentFileSize,
fileCount: lastFileIndex - index + 1,
});
while (index <= lastFileIndex) {
const tileSize = Math.min(columns, lastFileIndex - index + 1);
timeStampList.push({
itemType: ITEM_TYPE.TILE,
items: filteredData.slice(index, index + tileSize),
itemStartIndex: index,
});
index += tileSize;
}
}
};
const groupByTime = (timeStampList: TimeStampListItem[]) => {
let listItemIndex = 0;
let currentDate = -1;
@ -205,35 +300,7 @@ export function PhotoList({
});
}
});
if (!skipMerge) {
timeStampList = mergeTimeStampList(timeStampList, columns);
}
if (timeStampList.length === 0) {
timeStampList.push(getEmptyListItem());
}
if (
showAppDownloadBanner ||
publicCollectionGalleryContext.accessedThroughSharedURL
) {
timeStampList.push(getVacuumItem(timeStampList));
if (publicCollectionGalleryContext.accessedThroughSharedURL) {
timeStampList.push(getAlbumsFooter());
} else {
timeStampList.push(getAppDownloadFooter());
}
}
timeStampListRef.current = timeStampList;
filteredDataCopyRef.current = filteredData;
refreshList();
}, [
width,
height,
filteredData,
showAppDownloadBanner,
publicCollectionGalleryContext.accessedThroughSharedURL,
]);
};
const isSameDay = (first, second) =>
first.getFullYear() === second.getFullYear() &&
@ -386,6 +453,8 @@ export function PhotoList({
switch (timeStampList[index].itemType) {
case ITEM_TYPE.TIME:
return DATE_CONTAINER_HEIGHT;
case ITEM_TYPE.SIZE_AND_CNT:
return SIZE_AND_COUNT_CONTAINER_HEIGHT;
case ITEM_TYPE.TILE:
return listItemHeight;
default:
@ -425,6 +494,14 @@ export function PhotoList({
{listItem.date}
</DateContainer>
);
case ITEM_TYPE.SIZE_AND_CNT:
return (
<SizeAndCountContainer span={columns}>
{listItem.fileCount} {constants.FILES},{' '}
{getReadableSizeFromBytes(listItem.fileSize)}{' '}
{constants.EACH}
</SizeAndCountContainer>
);
case ITEM_TYPE.OTHER:
return listItem.item;
default: {

View file

@ -1,5 +1,6 @@
export const GAP_BTW_TILES = 4;
export const DATE_CONTAINER_HEIGHT = 48;
export const SIZE_AND_COUNT_CONTAINER_HEIGHT = 72;
export const IMAGE_CONTAINER_MAX_HEIGHT = 200;
export const IMAGE_CONTAINER_MAX_WIDTH =
IMAGE_CONTAINER_MAX_HEIGHT - GAP_BTW_TILES;

View file

@ -257,6 +257,7 @@ export default function Deduplicate() {
activeCollection={ALL_SECTION}
isSharedCollection={false}
enableDownload={true}
deduplicating={{ clubByTime: clubByTime }}
/>
) : (
<b

View file

@ -5,6 +5,7 @@ export interface fileAttribute {
encryptedData?: DataStream | Uint8Array;
objectKey?: string;
decryptionHeader: string;
size?: number;
}
export interface MagicMetadataCore {

View file

@ -41,3 +41,7 @@ export interface NotificationAttributes {
message: string;
title: string;
}
export interface DeduplicatingType {
clubByTime: boolean;
}

View file

@ -0,0 +1,9 @@
export const getReadableSizeFromBytes = (bytes: number) => {
const sizes = ['B', 'KB', 'MB', 'GB'];
let currSize = 0;
while (bytes >= 1024 && currSize < sizes.length) {
bytes /= 1024;
currSize++;
}
return `${bytes.toFixed(2)} ${sizes[currSize]}`;
};

View file

@ -692,6 +692,8 @@ const englishConstants = {
DEDUPLICATE_FILES: 'deduplicate files',
NO_DUPLICATES_FOUND: "you've no duplicate files that can be cleared",
CLUB_BY_CAPTURE_TIME: 'club by capture time',
FILES: 'files',
EACH: 'each',
};
export default englishConstants;