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
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
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 next2026-09-22 15:22:52 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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 storeinto
PhotoRecord/AlbumRecord(no keys, JSON-safe), one photo perfileIDdeduplicated across album memberships (all album ids kept), newest first.
subscribe({ onChange })returns{ unsubscribe }and delivers aLibraryChange— changed full records plus removed id sets — only when arefresh 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/editedTimeover basicmetadata;
takenAtis exposed in milliseconds, so it divides the Entemicrosecond 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):
captionhas no existing repo fixture; mapped frompubMagicMetadata.captionand covered by a new test fixture.
LibrarySnapshot.takenAtis wall-clock ms at snapshot time.thumbnailPath/originalPathare declared but left unset until a latercaching phase populates them.
Model: opus-4-8
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-8PASS —
snapshot()andsubscribe()meet the definition of done: a synchronous, key-free, deduplicated projection with correct edited-name/time precedence (pubMagicMetadataover basic metadata) and milliseconds, deltas that fire only when a refresh actually changes the projection and never on a no-op,unsubscribethat stops delivery, magic-metadata field names checked against the repo fixtures (w/h,visibility;captiondisclosed 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 currentnext.Model: opus-4-8