diff --git a/src/components/PhotoFrame.tsx b/src/components/PhotoFrame.tsx index cded5f043..a4ce581d8 100644 --- a/src/components/PhotoFrame.tsx +++ b/src/components/PhotoFrame.tsx @@ -250,18 +250,15 @@ const PhotoFrame = ({ }, [open]); const updateURL = (index: number) => (url: string) => { - files[index] = { - ...files[index], - msrc: url, - src: files[index].src ? files[index].src : url, - w: window.innerWidth, - h: window.innerHeight, - }; - if ( - files[index].metadata.fileType === FILE_TYPE.VIDEO && - !files[index].html - ) { - files[index].html = ` + const updateFile = (file: EnteFile) => { + file = { + ...file, + msrc: url, + w: window.innerWidth, + h: window.innerHeight, + }; + if (file.metadata.fileType === FILE_TYPE.VIDEO && !file.html) { + file.html = `
@@ -269,84 +266,94 @@ const PhotoFrame = ({
`; - delete files[index].src; - } else if ( - files[index].metadata.fileType === FILE_TYPE.LIVE_PHOTO && - !files[index].html - ) { - files[index].html = ` -
+ } else if ( + file.metadata.fileType === FILE_TYPE.LIVE_PHOTO && + !file.html + ) { + file.html = ` +
Loading...
`; - delete files[index].src; - } - if ( - files[index].metadata.fileType === FILE_TYPE.IMAGE && - !files[index].src - ) { - files[index].src = url; - } - setFiles(files); + } else if ( + file.metadata.fileType === FILE_TYPE.IMAGE && + !file.src + ) { + file.src = url; + } + return file; + }; + setFiles((files) => { + files[index] = updateFile(files[index]); + return [...files]; + }); + return updateFile(files[index]); }; const updateSrcURL = async (index: number, srcURL: SourceURL) => { - files[index] = { - ...files[index], - w: window.innerWidth, - h: window.innerHeight, - }; - const { imageURL, videoURL } = srcURL; - if (files[index].metadata.fileType === FILE_TYPE.VIDEO) { - if (await isPlaybackPossible(videoURL)) { - files[index].html = ` - - `; - } else { - files[index].html = ` -
- -
- ${constants.VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD} - Download -
+ const { videoURL, imageURL } = srcURL; + const isPlayable = videoURL && (await isPlaybackPossible(videoURL)); + const updateFile = (file: EnteFile) => { + file = { + ...file, + w: window.innerWidth, + h: window.innerHeight, + }; + if (file.metadata.fileType === FILE_TYPE.VIDEO) { + if (isPlayable) { + file.html = ` + + `; + } else { + file.html = ` + + `; + } + } else if (file.metadata.fileType === FILE_TYPE.LIVE_PHOTO) { + if (isPlayable) { + file.html = `
- -
`; - } else { - files[index].html = ` + } else { + file.html = `
- -
+ +
${constants.VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD}
`; + } + } else { + file.src = imageURL; } - } else { - files[index].src = imageURL; - } + return file; + }; + setFiles((files) => { + files[index] = updateFile(files[index]); + return [...files]; + }); setIsSourceLoaded(true); - setFiles(files); + return updateFile(files[index]); }; const handleClose = (needUpdate) => { @@ -462,13 +469,13 @@ const PhotoFrame = ({ } galleryContext.thumbs.set(item.id, url); } - updateURL(item.dataIndex)(url); - item.msrc = url; - if (!item.src) { - item.src = url; - } - item.w = window.innerWidth; - item.h = window.innerHeight; + const newFile = updateURL(item.dataIndex)(url); + item.msrc = newFile.msrc; + item.html = newFile.html; + item.src = newFile.src; + item.w = newFile.w; + item.h = newFile.h; + try { instance.invalidateCurrItems(); instance.updateSize(true); @@ -487,6 +494,7 @@ const PhotoFrame = ({ const mergedURL = galleryContext.files.get(item.id); urls = mergedURL.split(','); } else { + galleryContext.startLoading(); if ( publicCollectionGalleryContext.accessedThroughSharedURL ) { @@ -499,6 +507,7 @@ const PhotoFrame = ({ } else { urls = await DownloadManager.getFile(item, true); } + galleryContext.finishLoading(); const mergedURL = urls.join(','); galleryContext.files.set(item.id, mergedURL); } @@ -512,11 +521,15 @@ const PhotoFrame = ({ [imageURL] = urls; } setIsSourceLoaded(false); - await updateSrcURL(item.dataIndex, { imageURL, videoURL }); - item.html = files[item.dataIndex].html; - item.src = files[item.dataIndex].src; - item.w = files[item.dataIndex].w; - item.h = files[item.dataIndex].h; + const newFile = await updateSrcURL(item.dataIndex, { + imageURL, + videoURL, + }); + item.msrc = newFile.msrc; + item.html = newFile.html; + item.src = newFile.src; + item.w = newFile.w; + item.h = newFile.h; try { instance.invalidateCurrItems(); instance.updateSize(true); diff --git a/src/components/PhotoSwipe/PhotoSwipe.tsx b/src/components/PhotoSwipe/PhotoSwipe.tsx index f6e3168f8..2c5e7ea19 100644 --- a/src/components/PhotoSwipe/PhotoSwipe.tsx +++ b/src/components/PhotoSwipe/PhotoSwipe.tsx @@ -505,7 +505,8 @@ function InfoModal({ function PhotoSwipe(props: Iprops) { const pswpElement = useRef(); - const [photoSwipe, setPhotoSwipe] = useState>(); + const [photoSwipe, setPhotoSwipe] = + useState>(); const { isOpen, items, isSourceLoaded } = props; const [isFav, setIsFav] = useState(false); @@ -610,7 +611,9 @@ function PhotoSwipe(props: Iprops) { `download-message` ) as HTMLCollectionOf; for (const downloadMessageDiv of downloadMessageDivs) { - if (downloadMessageDiv?.dataset?.id === item.id) { + if ( + String(downloadMessageDiv?.dataset?.id) === String(item.id) + ) { const downloadLivePhotoBtn = downloadMessageDiv.firstElementChild as HTMLButtonElement; diff --git a/src/components/pages/gallery/PreviewCard.tsx b/src/components/pages/gallery/PreviewCard.tsx index 1a4810528..51a100226 100644 --- a/src/components/pages/gallery/PreviewCard.tsx +++ b/src/components/pages/gallery/PreviewCard.tsx @@ -164,7 +164,7 @@ const Cont = styled.div<{ disabled: boolean; selected: boolean }>` export default function PreviewCard(props: IProps) { const [imgSrc, setImgSrc] = useState(); - const { thumbs, files } = useContext(GalleryContext); + const { thumbs } = useContext(GalleryContext); const { file, onClick, @@ -203,10 +203,6 @@ export default function PreviewCard(props: IProps) { if (isMounted.current) { setImgSrc(url); thumbs.set(file.id, url); - file.msrc = url; - if (!file.src) { - file.src = url; - } updateURL(url); } } catch (e) { @@ -218,13 +214,6 @@ export default function PreviewCard(props: IProps) { const thumbImgSrc = thumbs.get(file.id); setImgSrc(thumbImgSrc); file.msrc = thumbImgSrc; - if (!file.src) { - if (files.has(file.id)) { - file.src = files.get(file.id); - } else { - file.src = thumbImgSrc; - } - } } else { main(); } diff --git a/src/services/fileService.ts b/src/services/fileService.ts index 8d1ad4944..540f0dbfe 100644 --- a/src/services/fileService.ts +++ b/src/services/fileService.ts @@ -6,9 +6,15 @@ import { EncryptionResult } from 'types/upload'; import { Collection } from 'types/collection'; import HTTPService from './HTTPService'; import { logError } from 'utils/sentry'; -import { decryptFile, mergeMetadata, sortFiles } from 'utils/file'; +import { + decryptFile, + mergeMetadata, + preservePhotoswipeProps, + sortFiles, +} from 'utils/file'; import CryptoWorker from 'utils/crypto'; import { EnteFile, TrashRequest, UpdateMagicMetadataRequest } from 'types/file'; +import { SetFiles } from 'types/gallery'; const ENDPOINT = getEndpoint(); const FILES_TABLE = 'files'; @@ -28,13 +34,13 @@ const getCollectionLastSyncTime = async (collection: Collection) => export const syncFiles = async ( collections: Collection[], - setFiles: (files: EnteFile[]) => void + setFiles: SetFiles ) => { const localFiles = await getLocalFiles(); let files = await removeDeletedCollectionFiles(collections, localFiles); if (files.length !== localFiles.length) { await setLocalFiles(files); - setFiles([...sortFiles(mergeMetadata(files))]); + setFiles(preservePhotoswipeProps([...sortFiles(mergeMetadata(files))])); } for (const collection of collections) { if (!getToken()) { @@ -70,7 +76,7 @@ export const syncFiles = async ( `${collection.id}-time`, collection.updationTime ); - setFiles([...sortFiles(mergeMetadata(files))]); + setFiles(preservePhotoswipeProps([...sortFiles(mergeMetadata(files))])); } return sortFiles(mergeMetadata(files)); }; @@ -79,7 +85,7 @@ export const getFiles = async ( collection: Collection, sinceTime: number, files: EnteFile[], - setFiles: (files: EnteFile[]) => void + setFiles: SetFiles ): Promise => { try { const decryptedFiles: EnteFile[] = []; @@ -116,10 +122,12 @@ export const getFiles = async ( time = resp.data.diff.slice(-1)[0].updationTime; } setFiles( - sortFiles( - mergeMetadata( - [...(files || []), ...decryptedFiles].filter( - (item) => !item.isDeleted + preservePhotoswipeProps( + sortFiles( + mergeMetadata( + [...(files || []), ...decryptedFiles].filter( + (item) => !item.isDeleted + ) ) ) ) diff --git a/src/services/trashService.ts b/src/services/trashService.ts index c53413074..4fba7c05e 100644 --- a/src/services/trashService.ts +++ b/src/services/trashService.ts @@ -2,7 +2,12 @@ import { SetFiles } from 'types/gallery'; import { Collection } from 'types/collection'; import { getEndpoint } from 'utils/common/apiUtil'; import { getToken } from 'utils/common/key'; -import { decryptFile, mergeMetadata, sortFiles } from 'utils/file'; +import { + decryptFile, + mergeMetadata, + preservePhotoswipeProps, + sortFiles, +} from 'utils/file'; import { logError } from 'utils/sentry'; import localForage from 'utils/storage/localForage'; import { getCollection } from './collectionService'; @@ -120,7 +125,12 @@ export const updateTrash = async ( updatedTrash = removeRestoredOrDeletedTrashItems(updatedTrash); setFiles( - sortFiles([...(files ?? []), ...getTrashedFiles(updatedTrash)]) + preservePhotoswipeProps( + sortFiles([ + ...(files ?? []), + ...getTrashedFiles(updatedTrash), + ]) + ) ); await localForage.setItem(TRASH, updatedTrash); await localForage.setItem(TRASH_TIME, time); diff --git a/src/services/upload/thumbnailService.ts b/src/services/upload/thumbnailService.ts index b6f1d3903..baa1a9c61 100644 --- a/src/services/upload/thumbnailService.ts +++ b/src/services/upload/thumbnailService.ts @@ -15,7 +15,7 @@ const MAX_THUMBNAIL_SIZE = 100 * 1024; const MIN_QUALITY = 0.5; const MAX_QUALITY = 0.7; -const WAIT_TIME_THUMBNAIL_GENERATION = 10 * 1000; +const WAIT_TIME_THUMBNAIL_GENERATION = 30 * 1000; interface Dimension { width: number; diff --git a/src/services/upload/uploadManager.ts b/src/services/upload/uploadManager.ts index eeeceda0f..e40e83fca 100644 --- a/src/services/upload/uploadManager.ts +++ b/src/services/upload/uploadManager.ts @@ -5,7 +5,7 @@ import { getDedicatedCryptoWorker } from 'utils/crypto'; import { sortFilesIntoCollections, sortFiles, - removeUnnecessaryFileProps, + preservePhotoswipeProps, } from 'utils/file'; import { logError } from 'utils/sentry'; import { getMetadataJSONMapKey, parseMetadataJSON } from './metadataService'; @@ -239,10 +239,8 @@ class UploadManager { if (fileUploadResult === FileUploadResults.UPLOADED) { this.existingFiles.push(file); this.existingFiles = sortFiles(this.existingFiles); - await setLocalFiles( - removeUnnecessaryFileProps(this.existingFiles) - ); - this.setFiles(this.existingFiles); + await setLocalFiles(this.existingFiles); + this.setFiles(preservePhotoswipeProps(this.existingFiles)); if (!this.existingFilesCollectionWise.has(file.collectionID)) { this.existingFilesCollectionWise.set(file.collectionID, []); } diff --git a/src/utils/file/index.ts b/src/utils/file/index.ts index 42c2dc4ea..5ad062ed8 100644 --- a/src/utils/file/index.ts +++ b/src/utils/file/index.ts @@ -282,20 +282,18 @@ export async function decryptFile(file: EnteFile, collectionKey: string) { } } -export function removeUnnecessaryFileProps(files: EnteFile[]): EnteFile[] { - const stripedFiles = files.map((file) => { - delete file.src; - delete file.msrc; - delete file.file.objectKey; - delete file.thumbnail.objectKey; - delete file.h; - delete file.html; - delete file.w; - - return file; - }); - return stripedFiles; -} +export const preservePhotoswipeProps = + (newFiles: EnteFile[]) => + (currentFiles: EnteFile[]): EnteFile[] => { + const currentFilesMap = Object.fromEntries( + currentFiles.map((file) => [file.id, file]) + ); + const fileWithPreservedProperty = newFiles.map((file) => { + const currentFile = currentFilesMap[file.id]; + return { ...currentFile, ...file }; + }); + return fileWithPreservedProperty; + }; export function fileNameWithoutExtension(filename) { const lastDotPosition = filename.lastIndexOf('.');