duplicates: perceptual hash + soft-mark resolution + upload 409

Adds pHash + dHash columns alongside the existing blake3 content_hash so
near-duplicates (re-encoded, resized, format-converted copies) become
queryable. /duplicates/{exact,perceptual} return groups; /duplicates/
{resolve,unresolve} flip a duplicate_of_hash soft-mark on losing rows
and union perceptual-only tag sets onto the survivor. The default
/photos listing filters duplicate_of_hash IS NULL so demoted siblings
stop cluttering the grid; include_duplicates=true opts back in for
Apollo's review modal. Upload now hashes bytes pre-write and returns
409 with the canonical sibling when a file's bytes already exist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cameron Cordes
2026-05-03 17:36:01 -04:00
parent 4340b164eb
commit 7584cd8792
14 changed files with 1852 additions and 1 deletions

View File

@@ -165,6 +165,15 @@ pub struct FilesRequest {
/// Optional library filter. Accepts a library id (e.g. "1") or name
/// (e.g. "main"). When omitted, results span all libraries.
pub library: Option<String>,
/// When true, include rows soft-marked as duplicates of another file
/// (i.e. `image_exif.duplicate_of_hash IS NOT NULL`). Default false —
/// the standard /photos listing hides demoted siblings so the grid
/// silently shrinks after a resolve. The Apollo duplicates modal
/// passes `true` so it can show both survivors and demoted members
/// inside a group.
#[serde(default)]
pub include_duplicates: Option<bool>,
}
#[derive(Copy, Clone, Deserialize, PartialEq, Debug)]