diff --git a/web/apps/photos/src/utils/file/index.ts b/web/apps/photos/src/utils/file/index.ts index ff5ac45d2e..f40e791027 100644 --- a/web/apps/photos/src/utils/file/index.ts +++ b/web/apps/photos/src/utils/file/index.ts @@ -4,6 +4,7 @@ import { type Electron } from "@/base/types/ipc"; import { FILE_TYPE } from "@/media/file-type"; import { decodeLivePhoto } from "@/media/live-photo"; import DownloadManager from "@/new/photos/services/download"; +import { setJPEGExifDateTimeOriginal } from "@/new/photos/services/exif-update"; import { EncryptedEnteFile, EnteFile, @@ -25,7 +26,6 @@ import type { User } from "@ente/shared/user/types"; import { downloadUsingAnchor } from "@ente/shared/utils"; import { t } from "i18next"; import { moveToHiddenCollection } from "services/collectionService"; -import { updateFileCreationDateInEXIF } from "@/new/photos/services/exif"; import { deleteFromTrash, trashFiles, @@ -81,7 +81,7 @@ export const streamWithUpdatedExif = async ( (extension == "jpeg" || extension == "jpg") ) { const fileBlob = await new Response(stream).blob(); - const updatedFileBlob = await updateFileCreationDateInEXIF( + const updatedFileBlob = await setJPEGExifDateTimeOriginal( fileBlob, new Date(enteFile.pubMagicMetadata.data.editedTime / 1000), ); diff --git a/web/packages/new/photos/services/exif-update.ts b/web/packages/new/photos/services/exif-update.ts index c08d404d5c..afc591510a 100644 --- a/web/packages/new/photos/services/exif-update.ts +++ b/web/packages/new/photos/services/exif-update.ts @@ -1,12 +1,23 @@ import log from "@/base/log"; import piexif from "piexifjs"; -export const updateFileCreationDateInEXIF = async ( - fileBlob: Blob, +/** + * Return a new blob with the "DateTimeOriginal" Exif tag set to the given + * {@link date}. + * + * @param jpegBlob A {@link Blob} containing JPEG data. + * + * @param date A {@link Date} to use as the value for the Exif + * "DateTimeOriginal" tag. + * + * @returns A new blob derived from {@link jpegBlob} but with the updated date. + */ +export const setJPEGExifDateTimeOriginal = async ( + jpegBlob: Blob, updatedDate: Date, ) => { try { - let imageDataURL = await blobToDataURL(fileBlob); + let imageDataURL = await blobToDataURL(jpegBlob); // Since we pass a Blob without an associated type, we get back a // generic data URL like "data:application/octet-stream;base64,...". // Modify it to have a `image/jpeg` MIME type. @@ -26,7 +37,7 @@ export const updateFileCreationDateInEXIF = async ( return dataURLToBlob(exifInsertedFile); } catch (e) { log.error("updateFileModifyDateInEXIF failed", e); - return fileBlob; + return jpegBlob; } }; @@ -55,8 +66,9 @@ const blobToDataURL = (blob: Blob) => const dataURLToBlob = (dataURI: string) => fetch(dataURI).then((res) => res.blob()); -function convertToExifDateFormat(date: Date) { - return `${date.getFullYear()}:${ - date.getMonth() + 1 - }:${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`; -} +/** + * Convert the given {@link Date} to a format that is expected by Exif for the + * DateTimeOriginal tag. + */ +const convertToExifDateFormat = (date: Date) => + `${date.getFullYear()}:${date.getMonth() + 1}:${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`; diff --git a/web/packages/new/photos/types/file.ts b/web/packages/new/photos/types/file.ts index 7cbbb8eb38..b24ea54a75 100644 --- a/web/packages/new/photos/types/file.ts +++ b/web/packages/new/photos/types/file.ts @@ -116,6 +116,11 @@ export interface FileMagicMetadataProps { export type FileMagicMetadata = MagicMetadataCore; export interface FilePublicMagicMetadataProps { + /** + * Modified value of the date time associated with an {@link EnteFile}. + * + * Epoch microseconds. + */ editedTime?: number; editedName?: string; caption?: string;