Merge branch 'main' into fix-1554

This commit is contained in:
Abhinav Kumar 2024-01-22 16:35:53 +05:30 committed by GitHub
commit be547a6cf5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 163 additions and 27 deletions

View file

@ -85,9 +85,9 @@
"ZOOM_IN_OUT": "In/uitzoomen",
"PREVIOUS": "Vorige (←)",
"NEXT": "Volgende (→)",
"TITLE_PHOTOS": "",
"TITLE_ALBUMS": "",
"TITLE_AUTH": "",
"TITLE_PHOTOS": "Ente Foto's",
"TITLE_ALBUMS": "Ente Foto's",
"TITLE_AUTH": "Ente Auth",
"UPLOAD_FIRST_PHOTO": "Je eerste foto uploaden",
"IMPORT_YOUR_FOLDERS": "Importeer uw mappen",
"UPLOAD_DROPZONE_MESSAGE": "Sleep om een back-up van je bestanden te maken",
@ -622,7 +622,7 @@
"PHOTO_EDITOR": "Fotobewerker",
"FASTER_UPLOAD": "Snellere uploads",
"FASTER_UPLOAD_DESCRIPTION": "Uploaden door nabije servers",
"MAGIC_SEARCH_STATUS": "",
"MAGIC_SEARCH_STATUS": "Magische Zoekfunctie Status",
"INDEXED_ITEMS": "Geïndexeerde bestanden",
"CACHE_DIRECTORY": "Cache map"
}

View file

@ -140,8 +140,8 @@ function CollectionSelector({
? t('UNHIDE_TO_COLLECTION')
: t('SELECT_COLLECTION')}
</DialogTitleWithCloseButton>
<DialogContent>
<FlexWrapper flexWrap="wrap" gap={0.5}>
<DialogContent sx={{ '&&&': { padding: 0 } }}>
<FlexWrapper flexWrap="wrap" gap={'4px'} padding={'16px'}>
<AddCollectionButton
showNextModal={attributes.showNextModal}
/>

View file

@ -12,7 +12,6 @@ import PhotoViewer from 'components/PhotoViewer';
import { TRASH_SECTION } from 'constants/collection';
import { updateFileMsrcProps, updateFileSrcProps } from 'utils/photoFrame';
import { SelectedState } from 'types/gallery';
import { PublicCollectionGalleryContext } from 'utils/publicCollectionGallery';
import { useRouter } from 'next/router';
import { logError } from '@ente/shared/sentry';
import { addLogLine } from '@ente/shared/logging';
@ -89,9 +88,6 @@ const PhotoFrame = ({
[k: number]: boolean;
}>({});
const galleryContext = useContext(GalleryContext);
const publicCollectionGalleryContext = useContext(
PublicCollectionGalleryContext
);
const [rangeStart, setRangeStart] = useState(null);
const [currentHover, setCurrentHover] = useState(null);
const [isShiftKeyPressed, setIsShiftKeyPressed] = useState(false);
@ -315,9 +311,7 @@ const PhotoFrame = ({
file={item}
updateURL={updateURL(index)}
onClick={onThumbnailClick(index)}
selectable={
!publicCollectionGalleryContext?.accessedThroughSharedURL
}
selectable={enableDownload}
onSelect={handleSelect(
item.id,
item.ownerID === galleryContext.user?.id,

View file

@ -192,6 +192,12 @@ function PhotoViewer(props: Iprops) {
case 'L':
onFavClick(photoSwipe?.currItem as EnteFile);
break;
case 'ArrowLeft':
handleArrowClick(event, 'left');
break;
case 'ArrowRight':
handleArrowClick(event, 'right');
break;
default:
break;
}
@ -352,6 +358,7 @@ function PhotoViewer(props: Iprops) {
maxSpreadZoom: 5,
index: currentIndex,
showHideOpacity: true,
arrowKeys: false,
getDoubleTapZoom(isMouseClick, item) {
if (isMouseClick) {
return 2.5;
@ -505,6 +512,24 @@ function PhotoViewer(props: Iprops) {
appContext.setDialogMessage(getTrashFileMessage(() => trashFile(file)));
};
const handleArrowClick = (
e: KeyboardEvent,
direction: 'left' | 'right'
) => {
// ignore arrow clicks if the user is typing in a text field
if (
e.target instanceof HTMLInputElement ||
e.target instanceof HTMLTextAreaElement
) {
return;
}
if (direction === 'left') {
photoSwipe.prev();
} else {
photoSwipe.next();
}
};
const updateItems = (items: EnteFile[]) => {
try {
if (photoSwipe) {

View file

@ -12,6 +12,7 @@ import UploadProgressContext from 'contexts/uploadProgress';
import { t } from 'i18next';
import { UPLOAD_STAGES } from 'constants/upload';
import { CaptionedText } from 'components/CaptionedText';
export const InProgressSection = () => {
const { inProgressUploads, hasLivePhotos, uploadFileNames, uploadStage } =
@ -44,9 +45,14 @@ export const InProgressSection = () => {
return (
<UploadProgressSection>
<UploadProgressSectionTitle expandIcon={<ExpandMoreIcon />}>
{uploadStage === UPLOAD_STAGES.EXTRACTING_METADATA
? t('INPROGRESS_METADATA_EXTRACTION')
: t('INPROGRESS_UPLOADS')}
<CaptionedText
mainText={
uploadStage === UPLOAD_STAGES.EXTRACTING_METADATA
? t('INPROGRESS_METADATA_EXTRACTION')
: t('INPROGRESS_UPLOADS')
}
subText={String(inProgressUploads?.length ?? 0)}
/>
</UploadProgressSectionTitle>
<UploadProgressSectionContent>
{hasLivePhotos && (

View file

@ -1,6 +1,5 @@
import React, { useContext } from 'react';
import { useContext } from 'react';
import ItemList from 'components/ItemList';
import { Typography } from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { ResultItemContainer } from './styledComponents';
import { UPLOAD_RESULT } from 'constants/upload';
@ -11,6 +10,7 @@ import {
UploadProgressSectionTitle,
} from './section';
import UploadProgressContext from 'contexts/uploadProgress';
import { CaptionedText } from 'components/CaptionedText';
export interface ResultSectionProps {
uploadResult: UPLOAD_RESULT;
@ -46,7 +46,10 @@ export const ResultSection = (props: ResultSectionProps) => {
return (
<UploadProgressSection>
<UploadProgressSectionTitle expandIcon={<ExpandMoreIcon />}>
<Typography> {props.sectionTitle}</Typography>
<CaptionedText
mainText={props.sectionTitle}
subText={String(fileList?.length ?? 0)}
/>
</UploadProgressSectionTitle>
<UploadProgressSectionContent>
{props.sectionInfo && (

View file

@ -1,6 +1,6 @@
import React, { useContext, useEffect, useRef, useState } from 'react';
import { EnteFile } from 'types/file';
import { styled } from '@mui/material';
import { Tooltip, styled } from '@mui/material';
import PlayCircleOutlineOutlinedIcon from '@mui/icons-material/PlayCircleOutlineOutlined';
import DownloadManager from 'services/download';
import useLongPress from '@ente/shared/hooks/useLongPress';
@ -298,7 +298,7 @@ export default function PreviewCard(props: IProps) {
}
};
return (
const renderFn = () => (
<Cont
key={`thumb-${file.id}}`}
onClick={handleClick}
@ -360,4 +360,22 @@ export default function PreviewCard(props: IProps) {
)}
</Cont>
);
if (deduplicateContext.isOnDeduplicatePage) {
return (
<Tooltip
placement="bottom-start"
enterDelay={300}
enterNextDelay={100}
title={`${
file.metadata.title
} - ${deduplicateContext.collectionNameMap.get(
file.collectionID
)}`}>
{renderFn()}
</Tooltip>
);
} else {
return renderFn();
}
}

View file

@ -0,0 +1,49 @@
import { useContext } from 'react';
import { FluidContainer } from '@ente/shared/components/Container';
import { SelectionBar } from '@ente/shared/components/Navbar/SelectionBar';
import { AppContext } from 'pages/_app';
import { Box, IconButton, Stack, Tooltip } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
import DownloadIcon from '@mui/icons-material/Download';
import { t } from 'i18next';
import { formatNumber } from 'utils/number/format';
interface Props {
count: number;
ownCount: number;
clearSelection: () => void;
downloadFilesHelper: () => void;
}
const SelectedFileOptions = ({
downloadFilesHelper,
count,
ownCount,
clearSelection,
}: Props) => {
const { isMobile } = useContext(AppContext);
return (
<SelectionBar isMobile={isMobile}>
<FluidContainer>
<IconButton onClick={clearSelection}>
<CloseIcon />
</IconButton>
<Box ml={1.5}>
{formatNumber(count)} {t('SELECTED')}{' '}
{ownCount !== count &&
`(${formatNumber(ownCount)} ${t('YOURS')})`}
</Box>
</FluidContainer>
<Stack spacing={2} direction="row" mr={2}>
<Tooltip title={t('DOWNLOAD')}>
<IconButton onClick={downloadFilesHelper}>
<DownloadIcon />
</IconButton>
</Tooltip>
</Stack>
</SelectionBar>
);
};
export default SelectedFileOptions;

View file

@ -16,7 +16,13 @@ import {
} from 'services/publicCollectionService';
import { Collection } from 'types/collection';
import { EnteFile } from 'types/file';
import { downloadFile, mergeMetadata, sortFiles } from 'utils/file';
import {
downloadFile,
downloadFiles,
getSelectedFiles,
mergeMetadata,
sortFiles,
} from 'utils/file';
import { AppContext } from 'pages/_app';
import { PublicCollectionGalleryContext } from 'utils/publicCollectionGallery';
import { CustomError, parseSharingErrorCodes } from '@ente/shared/error';
@ -52,7 +58,7 @@ import UploadButton from 'components/Upload/UploadButton';
import bs58 from 'bs58';
import AddPhotoAlternateOutlined from '@mui/icons-material/AddPhotoAlternateOutlined';
import ComlinkCryptoWorker from '@ente/shared/crypto';
import { UploadTypeSelectorIntent } from 'types/gallery';
import { SelectedState, UploadTypeSelectorIntent } from 'types/gallery';
import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';
import MoreHoriz from '@mui/icons-material/MoreHoriz';
import OverflowMenu from '@ente/shared/components/OverflowMenu/menu';
@ -60,6 +66,7 @@ import { OverflowMenuOption } from '@ente/shared/components/OverflowMenu/option'
import { ENTE_WEBSITE_LINK } from '@ente/shared/constants/urls';
import { APPS } from '@ente/shared/apps/constants';
import downloadManager from 'services/download';
import SelectedFileOptions from 'components/pages/sharedAlbum/SelectedFileOptions';
export default function PublicCollectionGallery() {
const token = useRef<string>(null);
@ -87,6 +94,12 @@ export default function PublicCollectionGallery() {
const [blockingLoad, setBlockingLoad] = useState(false);
const [shouldDisableDropzone, setShouldDisableDropzone] = useState(false);
const [selected, setSelected] = useState<SelectedState>({
ownCount: 0,
count: 0,
collectionID: 0,
});
const {
getRootProps: getDragAndDropRootProps,
getInputProps: getDragAndDropInputProps,
@ -441,6 +454,22 @@ export default function PublicCollectionGallery() {
}
}
const downloadFilesHelper = async () => {
try {
const selectedFiles = getSelectedFiles(selected, publicFiles);
await downloadFiles(selectedFiles);
} catch (e) {
logError(e, 'failed to download selected files');
}
};
const clearSelection = () => {
if (!selected?.count) {
return;
}
setSelected({ ownCount: 0, count: 0, collectionID: 0 });
};
return (
<PublicCollectionGalleryContext.Provider
value={{
@ -468,8 +497,8 @@ export default function PublicCollectionGallery() {
page={PAGES.SHARED_ALBUMS}
files={publicFiles}
syncWithRemote={syncWithRemote}
setSelected={() => null}
selected={{ count: 0, collectionID: null, ownCount: 0 }}
setSelected={setSelected}
selected={selected}
activeCollectionID={ALL_SECTION}
enableDownload={downloadEnabled}
fileToCollectionsMap={null}
@ -498,6 +527,14 @@ export default function PublicCollectionGallery() {
UploadTypeSelectorIntent.collectPhotos
}
/>
{selected.count > 0 && (
<SelectedFileOptions
downloadFilesHelper={downloadFilesHelper}
clearSelection={clearSelection}
count={selected.count}
ownCount={selected.ownCount}
/>
)}
</FullScreenDropZone>
</PublicCollectionGalleryContext.Provider>
);

View file

@ -26,7 +26,11 @@ export async function getDuplicates(
collectionNameMap: Map<number, string>
) {
try {
const dupes = await fetchDuplicateFileIDs();
const ascDupes = await fetchDuplicateFileIDs();
const descSortedDupes = ascDupes.sort((firstDupe, secondDupe) => {
return secondDupe.size - firstDupe.size;
});
const fileMap = new Map<number, EnteFile>();
for (const file of files) {
@ -35,7 +39,7 @@ export async function getDuplicates(
let result: Duplicate[] = [];
for (const dupe of dupes) {
for (const dupe of descSortedDupes) {
let duplicateFiles: EnteFile[] = [];
for (const fileID of dupe.fileIDs) {
if (fileMap.has(fileID)) {