Have photo.download() write to the save path of the Photo's own file copy
check / check (push) Successful in 4m9s
check / check (push) Successful in 4m9s
Photo.download() now hands the content cache the file copy the Photo holds, the one savePath and isLocal are dated from, instead of the fileID the cache then looked up in the store. A Photo held across a refresh that brings a date edited in Ente is now downloaded to the path its savePath names. A test covers that case. Model: opus-5-5
This commit is contained in:
+11
-10
@@ -117,8 +117,9 @@ export interface ContentOptions {
|
|||||||
export interface PhotoContent {
|
export interface PhotoContent {
|
||||||
original(fileID: number, opts?: ContentOptions): Promise<ContentResult>;
|
original(fileID: number, opts?: ContentOptions): Promise<ContentResult>;
|
||||||
thumbnail(fileID: number, opts?: ContentOptions): Promise<ContentResult>;
|
thumbnail(fileID: number, opts?: ContentOptions): Promise<ContentResult>;
|
||||||
// Put the original at its save path and return it there.
|
// Put the original at the save path of `file`, the copy the `Photo` holds,
|
||||||
download(fileID: number): Promise<ContentResult>;
|
// and return it there.
|
||||||
|
download(file: EnteFile): Promise<ContentResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EnsureResult {
|
export interface EnsureResult {
|
||||||
@@ -531,18 +532,18 @@ export class ContentCache implements PhotoContent, ThumbnailsAPI {
|
|||||||
return this.get(fileID, "thumbnail", "on-demand", opts?.onProgress);
|
return this.get(fileID, "thumbnail", "on-demand", opts?.onProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the original at its save path under the download directory and
|
// Put the original at the save path of `file` under the download directory
|
||||||
// return it there. One already stored there is returned as it is; one the
|
// and return it there. `file` is the copy the `Photo` holds, so the path is
|
||||||
// cache holds is copied from it; any other is fetched straight to the
|
// the one its `savePath` names, even after a refresh changed the date. One
|
||||||
// save path, with no copy left in the cache.
|
// already stored there is returned as it is; one the cache holds is copied
|
||||||
async download(fileID: number): Promise<ContentResult> {
|
// from it; any other is fetched straight to the save path, with no copy
|
||||||
const file = this.getFile(fileID);
|
// left in the cache.
|
||||||
if (!file) throw new Error(`content cache: unknown file ${fileID}`);
|
async download(file: EnteFile): Promise<ContentResult> {
|
||||||
const root = this.downloadDirectory;
|
const root = this.downloadDirectory;
|
||||||
const saved =
|
const saved =
|
||||||
storedAtSavePath(root, file) ??
|
storedAtSavePath(root, file) ??
|
||||||
(await placeOriginal(root, file, (dest) =>
|
(await placeOriginal(root, file, (dest) =>
|
||||||
this.backupOriginal(fileID, dest),
|
this.backupOriginal(file.id, dest),
|
||||||
));
|
));
|
||||||
return { ...saved, bytes: fileSize(saved.path) ?? 0 };
|
return { ...saved, bytes: fileSize(saved.path) ?? 0 };
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -134,7 +134,7 @@ export class Photo {
|
|||||||
// it, it is copied from there; otherwise it is fetched straight to
|
// it, it is copied from there; otherwise it is fetched straight to
|
||||||
// `savePath`.
|
// `savePath`.
|
||||||
async download(): Promise<ContentResult> {
|
async download(): Promise<ContentResult> {
|
||||||
return this.cacheOrThrow().download(this.rec.fileID);
|
return this.cacheOrThrow().download(this.file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// As `original`, for the thumbnail, through the thumbnail pool.
|
// As `original`, for the thumbnail, through the thumbnail pool.
|
||||||
|
|||||||
@@ -466,6 +466,48 @@ describe("Photo save path, local copy, content and EXIF", () => {
|
|||||||
await lib.close();
|
await lib.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("downloads a photo held across a refresh that edits its date to the save path it names", async () => {
|
||||||
|
// The same account, whose second refresh brings a date edited in Ente.
|
||||||
|
const edited = file(1, 1);
|
||||||
|
edited.updationTime = 2;
|
||||||
|
edited.pubMagicMetadata = {
|
||||||
|
editedTime: new Date(2026, 3, 15, 12).getTime() * 1000,
|
||||||
|
};
|
||||||
|
class DateEditedClient extends MockClient {
|
||||||
|
refreshes = 0;
|
||||||
|
override async collectionsSince(): Promise<CollectionsPage> {
|
||||||
|
this.refreshes++;
|
||||||
|
return {
|
||||||
|
collections: [
|
||||||
|
{ ...collection(1), updationTime: this.refreshes },
|
||||||
|
],
|
||||||
|
deleted: [],
|
||||||
|
cursor: this.refreshes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
override async filesSince(): Promise<FilesPage> {
|
||||||
|
return {
|
||||||
|
files: [this.refreshes === 1 ? file(1, 1) : edited],
|
||||||
|
deleted: [],
|
||||||
|
cursor: this.refreshes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const lib = await open({ client: new DateEditedClient() });
|
||||||
|
const photo = lib.photos.byID({ fileID: 1 })!;
|
||||||
|
|
||||||
|
await lib.fresh();
|
||||||
|
expect(lib.photos.byID({ fileID: 1 })!.takenAt).toBe(
|
||||||
|
new Date(2026, 3, 15, 12).getTime(),
|
||||||
|
);
|
||||||
|
|
||||||
|
const saved = await photo.download();
|
||||||
|
expect(saved.path).toBe(photo.savePath);
|
||||||
|
expect(saved.path).toBe(join(root, "backup", DAY, "2026-03-01.1.jpg"));
|
||||||
|
expect(photo.isLocal).toBe(true);
|
||||||
|
await lib.close();
|
||||||
|
});
|
||||||
|
|
||||||
it("has a save path, and is not local, without a content source", async () => {
|
it("has a save path, and is not local, without a content source", async () => {
|
||||||
const lib = await open({ contentSource: undefined });
|
const lib = await open({ contentSource: undefined });
|
||||||
const photo = lib.photos.byID({ fileID: 1 })!;
|
const photo = lib.photos.byID({ fileID: 1 })!;
|
||||||
|
|||||||
Reference in New Issue
Block a user