Plain-record library snapshot and change subscription #62

Merged
clawbot merged 1 commits from issue-43-snapshot-subscribe into next 2026-09-22 15:22:52 +02:00
Collaborator

Adds the plain-record snapshot and change subscription the GUI uses over
Electron IPC, extending the Library from
#42.

snapshot() is synchronous and reads only RAM: it projects the decrypted store
into PhotoRecord/AlbumRecord (no keys, JSON-safe), one photo per fileID
deduplicated across album memberships (all album ids kept), newest first.
subscribe({ onChange }) returns { unsubscribe } and delivers a
LibraryChange — changed full records plus removed id sets — only when a
refresh actually alters the projection; a no-op refresh delivers nothing. The
existing refresh loop drives it: after each committed refresh that changed the
store, the projection is recomputed and diffed against the previous one.

Field names were confirmed against the repo's own fixtures: w/h
(width/height) and private visibility (mapped to isArchived/isHidden).
Title/time precedence is pubMagicMetadata.editedName/editedTime over basic
metadata; takenAt is exposed in milliseconds, so it divides the Ente
microsecond value by 1000.

Not shown by the diff: the change fires on the RAM commit, decoupled from the
disk save, so reads and subscribers stay consistent even when a save fails (the
failure still surfaces through status().lastError).

Disclosures (judgement calls; scope did not specify):

  • caption has no existing repo fixture; mapped from pubMagicMetadata.caption
    and covered by a new test fixture.
  • LibrarySnapshot.takenAt is wall-clock ms at snapshot time.
  • Snapshot albums are ordered newest-updated first.
  • thumbnailPath/originalPath are declared but left unset until a later
    caching phase populates them.

Model: opus-4-8

Adds the plain-record snapshot and change subscription the GUI uses over Electron IPC, extending the Library from https://git.eeqj.de/sneak/quak/pulls/42. `snapshot()` is synchronous and reads only RAM: it projects the decrypted store into `PhotoRecord`/`AlbumRecord` (no keys, JSON-safe), one photo per `fileID` deduplicated across album memberships (all album ids kept), newest first. `subscribe({ onChange })` returns `{ unsubscribe }` and delivers a `LibraryChange` — changed full records plus removed id sets — only when a refresh actually alters the projection; a no-op refresh delivers nothing. The existing refresh loop drives it: after each committed refresh that changed the store, the projection is recomputed and diffed against the previous one. Field names were confirmed against the repo's own fixtures: `w`/`h` (width/height) and private `visibility` (mapped to isArchived/isHidden). Title/time precedence is `pubMagicMetadata.editedName`/`editedTime` over basic metadata; `takenAt` is exposed in milliseconds, so it divides the Ente microsecond value by 1000. Not shown by the diff: the change fires on the RAM commit, decoupled from the disk save, so reads and subscribers stay consistent even when a save fails (the failure still surfaces through `status().lastError`). Disclosures (judgement calls; scope did not specify): - `caption` has no existing repo fixture; mapped from `pubMagicMetadata.caption` and covered by a new test fixture. - `LibrarySnapshot.takenAt` is wall-clock ms at snapshot time. - Snapshot albums are ordered newest-updated first. - `thumbnailPath`/`originalPath` are declared but left unset until a later caching phase populates them. Model: opus-4-8
clawbot self-assigned this 2026-09-22 15:05:41 +02:00
clawbot added 1 commit 2026-09-22 15:05:42 +02:00
Project the decrypted store into plain, key-free records the GUI reads
across Electron IPC: PhotoRecord, AlbumRecord, LibrarySnapshot, and the
LibraryChange a subscription delivers.

snapshot() is synchronous (RAM only): one PhotoRecord per fileID, deduped
across memberships with every album id, newest first. subscribe({ onChange })
fires a LibraryChange (changed full records plus removed id sets) only when a
refresh alters the projection; a no-op refresh fires nothing.

Magic-metadata field names are taken from the repo fixtures: w/h and
visibility. Edited-name/edited-time precedence is pubMagicMetadata over basic
metadata; takenAt is exposed in milliseconds (Ente stores microseconds).

Model: opus-4-8
clawbot added the needs-review label 2026-09-22 15:05:48 +02:00
Author
Collaborator

PASS — snapshot() and subscribe() meet the definition of done: a synchronous, key-free, deduplicated projection with correct edited-name/time precedence (pubMagicMetadata over basic metadata) and milliseconds, deltas that fire only when a refresh actually changes the projection and never on a no-op, unsubscribe that stops delivery, magic-metadata field names checked against the repo fixtures (w/h, visibility; caption disclosed as fixture-less and covered by a new test), reuse of the existing refresh loop and store rather than a reimplementation, and mock-client tests that fail under mutation, with the gate green on the head rebased onto current next.

Model: opus-4-8

PASS — `snapshot()` and `subscribe()` meet the definition of done: a synchronous, key-free, deduplicated projection with correct edited-name/time precedence (`pubMagicMetadata` over basic metadata) and milliseconds, deltas that fire only when a refresh actually changes the projection and never on a no-op, `unsubscribe` that stops delivery, magic-metadata field names checked against the repo fixtures (`w`/`h`, `visibility`; `caption` disclosed as fixture-less and covered by a new test), reuse of the existing refresh loop and store rather than a reimplementation, and mock-client tests that fail under mutation, with the gate green on the head rebased onto current `next`. Model: opus-4-8
clawbot merged commit fbb8ae44a7 into next 2026-09-22 15:22:52 +02:00
clawbot deleted branch issue-43-snapshot-subscribe 2026-09-22 15:22:53 +02:00
Sign in to join this conversation.