From 8a2d3600e94cd80955176005bf85cebb2d2b7950 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 2 Aug 2024 14:18:57 +0530 Subject: [PATCH] wip move --- .../photos/src/components/FixCreationTime.tsx | 30 ++++ web/packages/new/photos/services/fix-exif.ts | 148 ++++++++---------- 2 files changed, 94 insertions(+), 84 deletions(-) diff --git a/web/apps/photos/src/components/FixCreationTime.tsx b/web/apps/photos/src/components/FixCreationTime.tsx index 0e585dbad6..41e344aac6 100644 --- a/web/apps/photos/src/components/FixCreationTime.tsx +++ b/web/apps/photos/src/components/FixCreationTime.tsx @@ -1,3 +1,4 @@ +import log from "@/base/log"; import type { ParsedMetadataDate } from "@/media/file-metadata"; import { PhotoDateTimePicker } from "@/new/photos/components/PhotoDateTimePicker"; import { @@ -5,6 +6,7 @@ import { type FixOption, } from "@/new/photos/services/fix-exif"; import { EnteFile } from "@/new/photos/types/file"; +import { fileLogID } from "@/new/photos/utils/file"; import DialogBox from "@ente/shared/components/DialogBox/"; import { Button, @@ -252,3 +254,31 @@ const Footer = ({ step, startFix, ...props }) => { ) ); }; + +type SetProgressTracker = React.Dispatch< + React.SetStateAction<{ + current: number; + total: number; + }> +>; + +const updateFiles = async ( + enteFiles: EnteFile[], + fixOption: FixOption, + customDate: ParsedMetadataDate, + setProgressTracker: SetProgressTracker, +) => { + setProgressTracker({ current: 0, total: enteFiles.length }); + let hadErrors = false; + for (const [i, enteFile] of enteFiles.entries()) { + try { + await updateEnteFileDate(enteFile, fixOption, customDate); + } catch (e) { + log.error(`Failed to update date of ${fileLogID(enteFile)}`, e); + hadErrors = true; + } finally { + setProgressTracker({ current: i + 1, total: enteFiles.length }); + } + } + return hadErrors; +}; diff --git a/web/packages/new/photos/services/fix-exif.ts b/web/packages/new/photos/services/fix-exif.ts index 98f19d35ea..9be79dcb1f 100644 --- a/web/packages/new/photos/services/fix-exif.ts +++ b/web/packages/new/photos/services/fix-exif.ts @@ -1,15 +1,14 @@ -import log from "@/base/log"; import type { ParsedMetadataDate } from "@/media/file-metadata"; +import { + changeFileCreationTime, + updateExistingFilePubMetadata, +} from "@/media/file-metadata"; import { FileType } from "@/media/file-type"; import downloadManager from "@/new/photos/services/download"; import type { EnteFile } from "@/new/photos/types/file"; import { detectFileTypeInfo } from "@/new/photos/utils/detect-type"; import { validateAndGetCreationUnixTimeInMicroSeconds } from "@ente/shared/time"; import { getParsedExifData } from "@ente/shared/utils/exif-old"; -import { - changeFileCreationTime, - updateExistingFilePubMetadata, -} from "utils/file"; const EXIF_TIME_TAGS = [ "DateTimeOriginal", @@ -19,93 +18,74 @@ const EXIF_TIME_TAGS = [ "MetadataDate", ]; -export type SetProgressTracker = React.Dispatch< - React.SetStateAction<{ - current: number; - total: number; - }> ->; - export type FixOption = | "date-time-original" | "date-time-digitized" | "metadata-date" | "custom"; -export async function updateDateTimeOfEnteFiles( - filesToBeUpdated: EnteFile[], +/** + * Update the date associated with a given {@link enteFile}. + * + * This is generally viewed as the creation date of the underlying asset + * (photo, video, live photo) that this file stores. + * + * - For images, this function allows us to update this date from the + * Exif and other metadata embedded in the file. + * + * - For all types of files (including images), this function allows us to + * update this date to an explicitly provided value. + * + * If an Exif-involving {@link FixOption} is passed for an non-image file, + * then that file is just skipped over. + * + * Note that the metadata associated with a file is immutable, and we + * instead modify the mutable metadata section associated with the file. See + * [Note: Metadatum] for more details. + */ +export const updateEnteFileDate = async ( + file: EnteFile, fixOption: FixOption, customDate: ParsedMetadataDate, - setProgressTracker: SetProgressTracker, -) { - let completedWithError = false; - try { - if (filesToBeUpdated.length === 0) { - return completedWithError; +) => { + let correctCreationTime: number | null; + if (fixOption === "custom") { + correctCreationTime = customDate.timestamp; + } else { + if (file.metadata.fileType !== FileType.image) { + return; } - setProgressTracker({ current: 0, total: filesToBeUpdated.length }); - for (const [index, file] of filesToBeUpdated.entries()) { - try { - let correctCreationTime: number; - if (fixOption === "custom-time") { - correctCreationTime = customDate.getTime() * 1000; - } else { - if (file.metadata.fileType !== FileType.image) { - continue; - } - const fileStream = await downloadManager.getFile(file); - const fileBlob = await new Response(fileStream).blob(); - const fileObject = new File( - [fileBlob], - file.metadata.title, - ); - const fileTypeInfo = await detectFileTypeInfo(fileObject); - const exifData = await getParsedExifData( - fileObject, - fileTypeInfo, - EXIF_TIME_TAGS, - ); - if (fixOption === "date-time-original") { - correctCreationTime = - validateAndGetCreationUnixTimeInMicroSeconds( - exifData?.DateTimeOriginal ?? - exifData?.DateCreated, - ); - } else if (fixOption === "date-time-digitized") { - correctCreationTime = - validateAndGetCreationUnixTimeInMicroSeconds( - exifData?.CreateDate, - ); - } else if (fixOption === "metadata-date") { - correctCreationTime = - validateAndGetCreationUnixTimeInMicroSeconds( - exifData?.MetadataDate, - ); - } - } - if ( - correctCreationTime && - correctCreationTime !== file.metadata.creationTime - ) { - const updatedFile = await changeFileCreationTime( - file, - correctCreationTime, - ); - updateExistingFilePubMetadata(file, updatedFile); - } - } catch (e) { - log.error("failed to updated a CreationTime With Exif", e); - completedWithError = true; - } finally { - setProgressTracker({ - current: index + 1, - total: filesToBeUpdated.length, - }); - } + const fileStream = await downloadManager.getFile(file); + const fileBlob = await new Response(fileStream).blob(); + const fileObject = new File([fileBlob], file.metadata.title); + const fileTypeInfo = await detectFileTypeInfo(fileObject); + const exifData = await getParsedExifData( + fileObject, + fileTypeInfo, + EXIF_TIME_TAGS, + ); + if (fixOption === "date-time-original") { + correctCreationTime = validateAndGetCreationUnixTimeInMicroSeconds( + exifData?.DateTimeOriginal ?? exifData?.DateCreated, + ); + } else if (fixOption === "date-time-digitized") { + correctCreationTime = validateAndGetCreationUnixTimeInMicroSeconds( + exifData?.CreateDate, + ); + } else if (fixOption === "metadata-date") { + correctCreationTime = validateAndGetCreationUnixTimeInMicroSeconds( + exifData?.MetadataDate, + ); } - } catch (e) { - log.error("update CreationTime With Exif failed", e); - completedWithError = true; } - return completedWithError; -} + if ( + correctCreationTime && + correctCreationTime !== file.metadata.creationTime + ) { + const updatedFile = await changeFileCreationTime( + file, + correctCreationTime, + ); + updateExistingFilePubMetadata(file, updatedFile); + } +};