In-process read surface: albums, photos, and timeline grouping (closes #44)
check / check (push) Successful in 25s

Adds the in-process read surface, served from RAM with args-object signatures: albums (list/byName/byID), photos (byID/records -> plain PhotoRecord[]), thin Album/Photo wrappers, and timeline.groups (day/week/month) with a PhotoFilter (albumID/text/fileTypes/hasLocation/includeArchived; hidden excluded). Week keys use ISO YYYY-Www; each file appears once per group, newest first. Built on the #43 snapshot projection; no network.

Model: opus-4-8
This commit was merged in pull request #64.
This commit is contained in:
2026-09-22 17:21:48 +02:00
parent 000d395c87
commit c5c1f387df
4 changed files with 922 additions and 0 deletions
+33
View File
@@ -31,6 +31,25 @@ import {
type LibrarySnapshot,
type LibraryChange,
} from "./records.js";
import {
makeAlbumsAPI,
makePhotosAPI,
makeTimelineAPI,
type AlbumsAPI,
type PhotosAPI,
type TimelineAPI,
} from "./read.js";
export {
Album,
Photo,
type AlbumsAPI,
type PhotosAPI,
type TimelineAPI,
type PhotoFilter,
type TimelineGroup,
type GroupBy,
} from "./read.js";
import type { CollectionsPage, FilesPage } from "../client.js";
import type { Collection, EnteFile } from "../model/types.js";
@@ -88,6 +107,13 @@ export class Library {
readonly cacheDirectory: string;
readonly downloadDirectory?: string;
// The in-process read surface (issue #44). Each namespace answers
// synchronously from the live record projection; no read touches the
// network.
readonly albums: AlbumsAPI;
readonly photos: PhotosAPI;
readonly timeline: TimelineAPI;
private readonly client: LibraryClient;
private readonly store: MetadataStore;
private readonly userID: number;
@@ -127,6 +153,13 @@ export class Library {
this.intervalMs = args.intervalMs;
this.onProgress = args.onProgress;
this.lastRecords = this.deriveNow();
// The read namespaces derive fresh from the store on each call, so they
// always reflect the latest refresh.
const derive = (): DerivedRecords => this.deriveNow();
this.albums = makeAlbumsAPI(derive);
this.photos = makePhotosAPI(derive);
this.timeline = makeTimelineAPI(derive);
}
// Load the cache and start the refresh loop. With an empty cache the first