diff --git a/web/apps/photos/src/components/PhotoFrame.tsx b/web/apps/photos/src/components/PhotoFrame.tsx index 3603e43535..e814b19623 100644 --- a/web/apps/photos/src/components/PhotoFrame.tsx +++ b/web/apps/photos/src/components/PhotoFrame.tsx @@ -2,6 +2,7 @@ import log from "@/base/log"; import { downloadManager, type LivePhotoSourceURL, + type LoadedLivePhotoSourceURL, type RenderableSourceURLs, } from "@/gallery/services/download"; import { EnteFile } from "@/media/file"; @@ -45,6 +46,16 @@ const PHOTOSWIPE_HASH_SUFFIX = "&opened"; export type DisplayFile = EnteFile & { src?: string; srcURLs?: RenderableSourceURLs; + /** + * An object URL corresponding to the image portion, if any, associated with + * the {@link DisplayFile}. + * + * - For images, this will be the object URL of the renderable image itself. + * - For live photos, this will be the object URL of the image portion of + * the live photo. + * - For videos, this will not be defined. + */ + associatedImageURL?: string | undefined; msrc?: string; html?: string; w?: number; @@ -550,7 +561,16 @@ const updateDisplayFileSource = ( : true; file.canForceConvert = srcURLs.canForceConvert; file.conversionFailed = !isRenderable; - file.srcURLs = srcURLs; + file.associatedImageURL = (() => { + switch (file.metadata.fileType) { + case FileType.image: + return srcURLs.url as string; + case FileType.livePhoto: + return (srcURLs.url as LoadedLivePhotoSourceURL).image; + default: + return undefined; + } + })(); if (!isRenderable) { file.isSourceLoaded = true; return; @@ -574,7 +594,7 @@ const updateDisplayFileSource = ( `; } else { const { image: imageURL, video: videoURL } = - url as LivePhotoSourceURL; + url as LoadedLivePhotoSourceURL; file.html = `
diff --git a/web/apps/photos/src/components/PhotoViewer/index.tsx b/web/apps/photos/src/components/PhotoViewer/index.tsx index 6dfdfd825a..5fe68294ef 100644 --- a/web/apps/photos/src/components/PhotoViewer/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/index.tsx @@ -6,10 +6,7 @@ import { Overlay } from "@/base/components/mui/Container"; import { type ModalVisibilityProps } from "@/base/components/utils/modal"; import { lowercaseExtension } from "@/base/file-name"; import log from "@/base/log"; -import { - downloadManager, - type LoadedLivePhotoSourceURL, -} from "@/gallery/services/download"; +import { downloadManager } from "@/gallery/services/download"; import { fileLogID, type EnteFile } from "@/media/file"; import { FileType } from "@/media/file-type"; import { isHEICExtension, needsJPEGConversion } from "@/media/formats"; @@ -365,11 +362,7 @@ function PhotoViewer(props: PhotoViewerProps) { return; } - const key = - file.metadata.fileType === FileType.image - ? file.src - : (file.srcURLs.url as LoadedLivePhotoSourceURL).image; - + const key = file.associatedImageURL; if (exifCopy?.current?.key === key) return; setExif({ key, value: undefined }); @@ -638,12 +631,16 @@ function PhotoViewer(props: PhotoViewerProps) { const checkExifAvailable = async (enteFile: DisplayFile) => { if (exifExtractionInProgress.current === enteFile.src) return; + const associatedImageURL = enteFile.associatedImageURL; + if (!associatedImageURL) { + assertionFailed(); + return; + } + try { exifExtractionInProgress.current = enteFile.src; const file = await getFileFromURL( - enteFile.metadata.fileType === FileType.image - ? (enteFile.src as string) - : (enteFile.srcURLs.url as LoadedLivePhotoSourceURL).image, + associatedImageURL, enteFile.metadata.title, ); const tags = await extractRawExif(file);