Photo: save path, is-local, content bytes, metadata and EXIF getters (closes #141)
check / check (push) Successful in 1m24s

`Photo` gains:

- `savePath` and `isLocal`: synchronous, disk only. Where `lib.backup()` writes the original under the library's `downloadDirectory`, and whether all of it is there; a copy only in the cache does not count.
- `content()` and `exif()`: async, may download. `exif()` reads the common EXIF fields of a JPEG and returns `{}` for anything else.
- The getters `modifiedAt` and `hash`, also on `PhotoRecord`, and `year`.

For a live photo the backup has not stored yet, `savePath` carries the title's extension, and the image may be stored under a different one. The JPEG EXIF scan moved to `src/exif.ts`. The exported `PhotoContent` interface gains `savePath` and `isLocal`.

Judgement call: `iso` is read only when the file stores it as a single number.

Model: opus-5-5
This commit was merged in pull request #142.
This commit is contained in:
2026-10-01 17:58:23 +02:00
parent e6825abcdb
commit 2b598d3622
12 changed files with 566 additions and 86 deletions
+12 -4
View File
@@ -5,10 +5,11 @@
// owner ruling 5). The decrypted `Collection`/`EnteFile` objects stay in RAM in
// the main process; the window only ever sees these records.
//
// Ente holds edited/basic times in microseconds; records expose `takenAt` in
// milliseconds. The magic-metadata field names below are the ones the Ente
// clients write, confirmed against the repo's own fixtures: `w`/`h` in
// test/cli/metadata-backup.test.ts, `visibility` in test/library/store.test.ts.
// Ente holds edited/basic times in microseconds; records expose `takenAt` and
// `modifiedAt` in milliseconds. The magic-metadata field names below are the
// ones the Ente clients write, confirmed against the repo's own fixtures:
// `w`/`h` in test/cli/metadata-backup.test.ts, `visibility` in
// test/library/store.test.ts.
import type {
Collection,
@@ -33,12 +34,17 @@ export interface PhotoRecord {
// Milliseconds. `pubMagicMetadata.editedTime` when the user edited the
// date, else basic-metadata `creationTime`.
takenAt: number;
// Milliseconds. Basic-metadata `modificationTime`.
modifiedAt: number;
fileType: FileType;
caption?: string;
width?: number;
height?: number;
latitude?: number;
longitude?: number;
// The content hash the uploader recorded (`FileMetadata.hash`); files from
// very old clients have none.
hash?: string;
isArchived: boolean;
isHidden: boolean;
// Local cache paths, set once a later phase caches the bytes; unset here.
@@ -125,6 +131,7 @@ const toPhotoRecord = (
albumIDs,
title: asString(pub.editedName) ?? rep.metadata.title,
takenAt: microsToMillis(takenAtMicros),
modifiedAt: microsToMillis(rep.metadata.modificationTime),
fileType: rep.metadata.fileType,
isArchived: visibility === VISIBILITY_ARCHIVED,
isHidden: visibility === VISIBILITY_HIDDEN,
@@ -140,6 +147,7 @@ const toPhotoRecord = (
record.latitude = rep.metadata.latitude;
if (rep.metadata.longitude !== undefined)
record.longitude = rep.metadata.longitude;
if (rep.metadata.hash !== undefined) record.hash = rep.metadata.hash;
return record;
};